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