1 /* 2 * Copyright (C) 2021-2022 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 FIXED_QUEUE_H 17 #define FIXED_QUEUE_H 18 19 #include <memory> 20 #include <mutex> 21 #include <queue> 22 #include "semaphore_utils.h" 23 24 namespace utility { 25 template<class T> 26 class FixedQueue { 27 public: 28 /** 29 * @brief Construct a new Fixed Queue object 30 * 31 * @param capacity Queue's capacity, default is 20. 32 * @since 6 33 */ 34 explicit FixedQueue(const size_t capacity = 20); 35 36 /** 37 * @brief Destroy the Fixed Queue object 38 * 39 * @since 6 40 */ 41 virtual ~FixedQueue(); 42 43 /** 44 * @brief Try push one record into FixedQueue. 45 * 46 * @param record Push record. 47 * @return Success push record return true, else return false. 48 * @since 6 49 */ 50 bool TryPush(T record); 51 52 /** 53 * @brief Push one record into FixedQueue. 54 * 55 * @param record Push record. 56 * @since 6 57 */ 58 void Push(T record); 59 60 /** 61 * @brief Try pop one record from FixedQueue. 62 * 63 * @param record Pop record object result. 64 * @return Success pop record return true, else return false. 65 * @since 6 66 */ 67 bool TryPop(T &record); 68 69 /** 70 * @brief Pop one record from FixedQueue. 71 * 72 * @param record Pop record object result. 73 * @since 6 74 */ 75 void Pop(T &record); 76 77 private: 78 std::queue<T> queue_ {}; 79 std::mutex mutex_ {}; 80 std::unique_ptr<Semaphore> enqueue_ {}; 81 std::unique_ptr<Semaphore> dequeue_ {}; 82 size_t capacity_ {20}; 83 84 BT_DISALLOW_COPY_AND_ASSIGN(FixedQueue); 85 }; 86 87 template<class T> FixedQueue(const size_t capacity)88FixedQueue<T>::FixedQueue(const size_t capacity) : capacity_(capacity) 89 { 90 enqueue_ = std::make_unique<Semaphore>(capacity_); 91 dequeue_ = std::make_unique<Semaphore>(0); 92 } 93 94 template<class T> ~FixedQueue()95FixedQueue<T>::~FixedQueue() 96 { 97 while (!queue_.empty()) { 98 queue_.pop(); 99 } 100 } 101 102 template<class T> TryPush(T record)103bool FixedQueue<T>::TryPush(T record) 104 { 105 if (!enqueue_->TryWait()) { 106 return false; 107 } else { 108 { 109 std::lock_guard<std::mutex> lock(mutex_); 110 queue_.push(std::move(record)); 111 } 112 dequeue_->Post(); 113 return true; 114 } 115 } 116 117 template<class T> Push(T record)118void FixedQueue<T>::Push(T record) 119 { 120 enqueue_->Wait(); 121 { 122 std::lock_guard<std::mutex> lock(mutex_); 123 queue_.push(std::move(record)); 124 } 125 dequeue_->Post(); 126 } 127 128 template<class T> TryPop(T & record)129bool FixedQueue<T>::TryPop(T &record) 130 { 131 if (!dequeue_->TryWait()) { 132 return false; 133 } else { 134 { 135 std::lock_guard<std::mutex> lock(mutex_); 136 record = std::move(queue_.front()); 137 queue_.pop(); 138 } 139 enqueue_->Post(); 140 return true; 141 } 142 } 143 144 template<class T> Pop(T & record)145void FixedQueue<T>::Pop(T &record) 146 { 147 dequeue_->Wait(); 148 { 149 std::lock_guard<std::mutex> lock(mutex_); 150 record = std::move(queue_.front()); 151 queue_.pop(); 152 } 153 enqueue_->Post(); 154 } 155 } // namespace utility 156 157 #endif // FIXED_QUEUE_H