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)88 FixedQueue<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()95 FixedQueue<T>::~FixedQueue()
96 {
97     while (!queue_.empty()) {
98         queue_.pop();
99     }
100 }
101 
102 template<class T>
TryPush(T record)103 bool 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)118 void 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)129 bool 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)145 void 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