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