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