1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#ifndef CHANNEL_H
17c29fa5a6Sopenharmony_ci#define CHANNEL_H
18c29fa5a6Sopenharmony_ci
19c29fa5a6Sopenharmony_ci#include <condition_variable>
20c29fa5a6Sopenharmony_ci#include <deque>
21c29fa5a6Sopenharmony_ci#include <memory>
22c29fa5a6Sopenharmony_ci#include <mutex>
23c29fa5a6Sopenharmony_ci#include <type_traits>
24c29fa5a6Sopenharmony_ci
25c29fa5a6Sopenharmony_cinamespace OHOS {
26c29fa5a6Sopenharmony_cinamespace Msdp {
27c29fa5a6Sopenharmony_cinamespace DeviceStatus {
28c29fa5a6Sopenharmony_ci
29c29fa5a6Sopenharmony_citemplate<typename Event>
30c29fa5a6Sopenharmony_ciclass Channel {
31c29fa5a6Sopenharmony_ci    static_assert(std::is_enum_v<Event> || std::is_integral_v<Event> ||
32c29fa5a6Sopenharmony_ci                  (std::is_class_v<Event> &&
33c29fa5a6Sopenharmony_ci                   std::is_default_constructible_v<Event> &&
34c29fa5a6Sopenharmony_ci                   std::is_copy_constructible_v<Event>));
35c29fa5a6Sopenharmony_ci
36c29fa5a6Sopenharmony_cipublic:
37c29fa5a6Sopenharmony_ci    enum ChannelError {
38c29fa5a6Sopenharmony_ci        NO_ERROR = 0,
39c29fa5a6Sopenharmony_ci        QUEUE_IS_FULL = -1,
40c29fa5a6Sopenharmony_ci        NO_CHANNEL = -2,
41c29fa5a6Sopenharmony_ci        INACTIVE_CHANNEL = -3,
42c29fa5a6Sopenharmony_ci    };
43c29fa5a6Sopenharmony_ci
44c29fa5a6Sopenharmony_ci    class Sender final {
45c29fa5a6Sopenharmony_ci        friend class Channel<Event>;
46c29fa5a6Sopenharmony_ci
47c29fa5a6Sopenharmony_ci    public:
48c29fa5a6Sopenharmony_ci        Sender() = default;
49c29fa5a6Sopenharmony_ci        ~Sender() = default;
50c29fa5a6Sopenharmony_ci
51c29fa5a6Sopenharmony_ci        Sender(const Sender &other)
52c29fa5a6Sopenharmony_ci            : channel_(other.channel_)
53c29fa5a6Sopenharmony_ci        {}
54c29fa5a6Sopenharmony_ci
55c29fa5a6Sopenharmony_ci        Sender(Sender &&other)
56c29fa5a6Sopenharmony_ci            : channel_(other.channel_)
57c29fa5a6Sopenharmony_ci        {
58c29fa5a6Sopenharmony_ci            other.channel_ = nullptr;
59c29fa5a6Sopenharmony_ci        }
60c29fa5a6Sopenharmony_ci
61c29fa5a6Sopenharmony_ci        Sender& operator=(const Sender &other)
62c29fa5a6Sopenharmony_ci        {
63c29fa5a6Sopenharmony_ci            channel_ = other.channel_;
64c29fa5a6Sopenharmony_ci            return *this;
65c29fa5a6Sopenharmony_ci        }
66c29fa5a6Sopenharmony_ci
67c29fa5a6Sopenharmony_ci        Sender& operator=(Sender &&other)
68c29fa5a6Sopenharmony_ci        {
69c29fa5a6Sopenharmony_ci            channel_ = other.channel_;
70c29fa5a6Sopenharmony_ci            other.channel_ = nullptr;
71c29fa5a6Sopenharmony_ci            return *this;
72c29fa5a6Sopenharmony_ci        }
73c29fa5a6Sopenharmony_ci
74c29fa5a6Sopenharmony_ci        int32_t Send(const Event &event)
75c29fa5a6Sopenharmony_ci        {
76c29fa5a6Sopenharmony_ci            if (channel_ == nullptr) {
77c29fa5a6Sopenharmony_ci                return ChannelError::NO_CHANNEL;
78c29fa5a6Sopenharmony_ci            }
79c29fa5a6Sopenharmony_ci            return channel_->Send(event);
80c29fa5a6Sopenharmony_ci        }
81c29fa5a6Sopenharmony_ci
82c29fa5a6Sopenharmony_ci    private:
83c29fa5a6Sopenharmony_ci        Sender(std::shared_ptr<Channel<Event>> channel)
84c29fa5a6Sopenharmony_ci            : channel_(channel)
85c29fa5a6Sopenharmony_ci        {}
86c29fa5a6Sopenharmony_ci
87c29fa5a6Sopenharmony_ci        std::shared_ptr<Channel<Event>> channel_ { nullptr };
88c29fa5a6Sopenharmony_ci    };
89c29fa5a6Sopenharmony_ci
90c29fa5a6Sopenharmony_ci    class Receiver final {
91c29fa5a6Sopenharmony_ci        friend class Channel<Event>;
92c29fa5a6Sopenharmony_ci
93c29fa5a6Sopenharmony_ci    public:
94c29fa5a6Sopenharmony_ci        Receiver() = default;
95c29fa5a6Sopenharmony_ci        ~Receiver() = default;
96c29fa5a6Sopenharmony_ci
97c29fa5a6Sopenharmony_ci        Receiver(const Receiver &other)
98c29fa5a6Sopenharmony_ci            : channel_(other.channel_)
99c29fa5a6Sopenharmony_ci        {}
100c29fa5a6Sopenharmony_ci
101c29fa5a6Sopenharmony_ci        Receiver(Receiver &&other)
102c29fa5a6Sopenharmony_ci            : channel_(other.channel_)
103c29fa5a6Sopenharmony_ci        {
104c29fa5a6Sopenharmony_ci            other.channel_ = nullptr;
105c29fa5a6Sopenharmony_ci        }
106c29fa5a6Sopenharmony_ci
107c29fa5a6Sopenharmony_ci        Receiver& operator=(const Receiver &other)
108c29fa5a6Sopenharmony_ci        {
109c29fa5a6Sopenharmony_ci            channel_ = other.channel_;
110c29fa5a6Sopenharmony_ci            return *this;
111c29fa5a6Sopenharmony_ci        }
112c29fa5a6Sopenharmony_ci
113c29fa5a6Sopenharmony_ci        Receiver& operator=(Receiver &&other)
114c29fa5a6Sopenharmony_ci        {
115c29fa5a6Sopenharmony_ci            channel_ = other.channel_;
116c29fa5a6Sopenharmony_ci            other.channel_ = nullptr;
117c29fa5a6Sopenharmony_ci            return *this;
118c29fa5a6Sopenharmony_ci        }
119c29fa5a6Sopenharmony_ci
120c29fa5a6Sopenharmony_ci        void Enable()
121c29fa5a6Sopenharmony_ci        {
122c29fa5a6Sopenharmony_ci            if (channel_ != nullptr) {
123c29fa5a6Sopenharmony_ci                channel_->Enable();
124c29fa5a6Sopenharmony_ci            }
125c29fa5a6Sopenharmony_ci        }
126c29fa5a6Sopenharmony_ci
127c29fa5a6Sopenharmony_ci        void Disable()
128c29fa5a6Sopenharmony_ci        {
129c29fa5a6Sopenharmony_ci            if (channel_ != nullptr) {
130c29fa5a6Sopenharmony_ci                channel_->Disable();
131c29fa5a6Sopenharmony_ci            }
132c29fa5a6Sopenharmony_ci        }
133c29fa5a6Sopenharmony_ci
134c29fa5a6Sopenharmony_ci        Event Peek()
135c29fa5a6Sopenharmony_ci        {
136c29fa5a6Sopenharmony_ci            return (channel_ != nullptr ? channel_->Peek() : Event());
137c29fa5a6Sopenharmony_ci        }
138c29fa5a6Sopenharmony_ci
139c29fa5a6Sopenharmony_ci        void Pop()
140c29fa5a6Sopenharmony_ci        {
141c29fa5a6Sopenharmony_ci            if (channel_ != nullptr) {
142c29fa5a6Sopenharmony_ci                channel_->Pop();
143c29fa5a6Sopenharmony_ci            }
144c29fa5a6Sopenharmony_ci        }
145c29fa5a6Sopenharmony_ci
146c29fa5a6Sopenharmony_ci        Event Receive()
147c29fa5a6Sopenharmony_ci        {
148c29fa5a6Sopenharmony_ci            return (channel_ != nullptr ? channel_->Receive() : Event());
149c29fa5a6Sopenharmony_ci        }
150c29fa5a6Sopenharmony_ci
151c29fa5a6Sopenharmony_ci    private:
152c29fa5a6Sopenharmony_ci        Receiver(std::shared_ptr<Channel<Event>> channel)
153c29fa5a6Sopenharmony_ci            : channel_(channel)
154c29fa5a6Sopenharmony_ci        {}
155c29fa5a6Sopenharmony_ci
156c29fa5a6Sopenharmony_ci        std::shared_ptr<Channel<Event>> channel_ { nullptr };
157c29fa5a6Sopenharmony_ci    };
158c29fa5a6Sopenharmony_ci
159c29fa5a6Sopenharmony_ci    Channel() = default;
160c29fa5a6Sopenharmony_ci    ~Channel() = default;
161c29fa5a6Sopenharmony_ci
162c29fa5a6Sopenharmony_ci    static std::pair<Sender, Receiver> OpenChannel();
163c29fa5a6Sopenharmony_ci
164c29fa5a6Sopenharmony_ciprivate:
165c29fa5a6Sopenharmony_ci    void Enable();
166c29fa5a6Sopenharmony_ci    void Disable();
167c29fa5a6Sopenharmony_ci    int32_t Send(const Event &event);
168c29fa5a6Sopenharmony_ci    Event Peek();
169c29fa5a6Sopenharmony_ci    void Pop();
170c29fa5a6Sopenharmony_ci    Event Receive();
171c29fa5a6Sopenharmony_ci
172c29fa5a6Sopenharmony_ci    static inline constexpr size_t QUEUE_CAPACITY { 1024 };
173c29fa5a6Sopenharmony_ci
174c29fa5a6Sopenharmony_ci    std::mutex lock_;
175c29fa5a6Sopenharmony_ci    bool isActive_ { false };
176c29fa5a6Sopenharmony_ci    std::condition_variable empty_;
177c29fa5a6Sopenharmony_ci    std::deque<Event> queue_;
178c29fa5a6Sopenharmony_ci};
179c29fa5a6Sopenharmony_ci
180c29fa5a6Sopenharmony_citemplate<typename Event>
181c29fa5a6Sopenharmony_cistd::pair<typename Channel<Event>::Sender, typename Channel<Event>::Receiver> Channel<Event>::OpenChannel()
182c29fa5a6Sopenharmony_ci{
183c29fa5a6Sopenharmony_ci    std::shared_ptr<Channel<Event>> channel = std::make_shared<Channel<Event>>();
184c29fa5a6Sopenharmony_ci    return std::make_pair(Channel<Event>::Sender(channel), Channel<Event>::Receiver(channel));
185c29fa5a6Sopenharmony_ci}
186c29fa5a6Sopenharmony_ci
187c29fa5a6Sopenharmony_citemplate<typename Event>
188c29fa5a6Sopenharmony_civoid Channel<Event>::Enable()
189c29fa5a6Sopenharmony_ci{
190c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
191c29fa5a6Sopenharmony_ci    isActive_ = true;
192c29fa5a6Sopenharmony_ci}
193c29fa5a6Sopenharmony_ci
194c29fa5a6Sopenharmony_citemplate<typename Event>
195c29fa5a6Sopenharmony_civoid Channel<Event>::Disable()
196c29fa5a6Sopenharmony_ci{
197c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
198c29fa5a6Sopenharmony_ci    isActive_ = false;
199c29fa5a6Sopenharmony_ci    queue_.clear();
200c29fa5a6Sopenharmony_ci}
201c29fa5a6Sopenharmony_ci
202c29fa5a6Sopenharmony_citemplate<typename Event>
203c29fa5a6Sopenharmony_ciint32_t Channel<Event>::Send(const Event &event)
204c29fa5a6Sopenharmony_ci{
205c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
206c29fa5a6Sopenharmony_ci    if (!isActive_) {
207c29fa5a6Sopenharmony_ci        return ChannelError::INACTIVE_CHANNEL;
208c29fa5a6Sopenharmony_ci    }
209c29fa5a6Sopenharmony_ci    if (queue_.size() >= QUEUE_CAPACITY) {
210c29fa5a6Sopenharmony_ci        return ChannelError::QUEUE_IS_FULL;
211c29fa5a6Sopenharmony_ci    }
212c29fa5a6Sopenharmony_ci    bool needNotify = queue_.empty();
213c29fa5a6Sopenharmony_ci    queue_.push_back(event);
214c29fa5a6Sopenharmony_ci    if (needNotify) {
215c29fa5a6Sopenharmony_ci        empty_.notify_all();
216c29fa5a6Sopenharmony_ci    }
217c29fa5a6Sopenharmony_ci    return ChannelError::NO_ERROR;
218c29fa5a6Sopenharmony_ci}
219c29fa5a6Sopenharmony_ci
220c29fa5a6Sopenharmony_citemplate<typename Event>
221c29fa5a6Sopenharmony_ciEvent Channel<Event>::Peek()
222c29fa5a6Sopenharmony_ci{
223c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
224c29fa5a6Sopenharmony_ci    if (queue_.empty()) {
225c29fa5a6Sopenharmony_ci        empty_.wait(lock, [this] {
226c29fa5a6Sopenharmony_ci            return !queue_.empty();
227c29fa5a6Sopenharmony_ci        });
228c29fa5a6Sopenharmony_ci    }
229c29fa5a6Sopenharmony_ci    return queue_.front();
230c29fa5a6Sopenharmony_ci}
231c29fa5a6Sopenharmony_ci
232c29fa5a6Sopenharmony_citemplate<typename Event>
233c29fa5a6Sopenharmony_civoid Channel<Event>::Pop()
234c29fa5a6Sopenharmony_ci{
235c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
236c29fa5a6Sopenharmony_ci    if (queue_.empty()) {
237c29fa5a6Sopenharmony_ci        empty_.wait(lock, [this] {
238c29fa5a6Sopenharmony_ci            return !queue_.empty();
239c29fa5a6Sopenharmony_ci        });
240c29fa5a6Sopenharmony_ci    }
241c29fa5a6Sopenharmony_ci    queue_.pop_front();
242c29fa5a6Sopenharmony_ci}
243c29fa5a6Sopenharmony_ci
244c29fa5a6Sopenharmony_citemplate<typename Event>
245c29fa5a6Sopenharmony_ciEvent Channel<Event>::Receive()
246c29fa5a6Sopenharmony_ci{
247c29fa5a6Sopenharmony_ci    std::unique_lock<std::mutex> lock(lock_);
248c29fa5a6Sopenharmony_ci    if (queue_.empty()) {
249c29fa5a6Sopenharmony_ci        empty_.wait(lock, [this] {
250c29fa5a6Sopenharmony_ci            return !queue_.empty();
251c29fa5a6Sopenharmony_ci        });
252c29fa5a6Sopenharmony_ci    }
253c29fa5a6Sopenharmony_ci    Event event = queue_.front();
254c29fa5a6Sopenharmony_ci    queue_.pop_front();
255c29fa5a6Sopenharmony_ci    return event;
256c29fa5a6Sopenharmony_ci}
257c29fa5a6Sopenharmony_ci} // namespace DeviceStatus
258c29fa5a6Sopenharmony_ci} // namespace Msdp
259c29fa5a6Sopenharmony_ci} // namespace OHOS
260c29fa5a6Sopenharmony_ci#endif // CHANNEL_H