TTKMusicPlayer  4.2.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
ttkconcurrentqueue.h
Go to the documentation of this file.
1 #ifndef TTKCONCURRENTQUEUE_H
2 #define TTKCONCURRENTQUEUE_H
3 
4 /***************************************************************************
5  * This file is part of the TTK Library Module project
6  * Copyright (C) 2015 - 2025 Greedysky Studio
7 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17 
18  * You should have received a copy of the GNU Lesser General Public License along
19  * with this program; If not, see <http://www.gnu.org/licenses/>.
20  ***************************************************************************/
21 
22 #include <queue>
23 #include <string.h>
24 #include <condition_variable>
25 
29 template <typename T>
31 {
32 public:
33 #ifndef USE_TTK_QUEUE
34 
37  TTKConcurrentQueue() noexcept
38  : m_queue(),
39  m_mutex(),
40  m_condition()
41  {
42 
43  }
44 
48  inline size_t size() const
49  {
50  std::lock_guard<std::mutex> lock(m_mutex);
51  return m_queue.size();
52  }
53 
57  inline bool empty() const
58  {
59  std::lock_guard<std::mutex> lock(m_mutex);
60  return m_queue.empty();
61  }
62 
66  inline void clear()
67  {
68  std::lock_guard<std::mutex> lock(m_mutex);
69  std::queue<T> empty;
70  std::swap(empty, m_queue);
71  }
72 
76  inline void push(const T &value)
77  {
78  std::lock_guard<std::mutex> lock(m_mutex);
79  m_queue.push(value);
80  m_condition.notify_one();
81  }
82 
86  inline bool pop(T &value, bool block = true)
87  {
88  // If user wants to retrieve data in non-blocking mode
89  if(block)
90  {
91  std::unique_lock<std::mutex> lock(m_mutex);
92  while(m_queue.empty())
93  {
94  m_condition.wait(lock);
95  }
96  }
97  else
98  {
99  std::lock_guard<std::mutex> lock(m_mutex);
100  if(m_queue.empty())
101  {
102  return false;
103  }
104  }
105 
106  value = std::move(m_queue.front());
107  m_queue.pop();
108  return true;
109  }
110 
111 private:
112  std::queue<T> m_queue;
113  mutable std::mutex m_mutex;
114  std::condition_variable m_condition;
115 #else
116 
119  explicit TTKConcurrentQueue(size_t capacity = 64)
120  : m_capacity(capacity),
121  m_size(0),
122  m_head(0),
123  m_tail(0),
124  m_buffer(new T[capacity])
125  {
126 
127  }
128 
132  ~TTKConcurrentQueue() noexcept
133  {
134  delete[] m_buffer;
135  }
136 
140  inline size_t size() const
141  {
142  std::lock_guard<std::mutex> lock(m_mutex);
143  return m_size;
144  }
145 
149  inline bool empty() const
150  {
151  std::lock_guard<std::mutex> lock(m_mutex);
152  return m_size == 0;
153  }
154 
158  inline bool full() const
159  {
160  std::lock_guard<std::mutex> lock(m_mutex);
161  return m_size == m_capacity;
162  }
163 
167  inline size_t capacity() const noexcept
168  {
169  return m_capacity;
170  }
171 
175  inline void clear()
176  {
177  std::lock_guard<std::mutex> lock(m_mutex);
178  m_size = m_head = m_tail = 0;
179  memset(m_buffer, 0, sizeof(T) * m_capacity);
180  }
181 
185  inline bool push(const T& value, bool block = true)
186  {
187  if(block)
188  {
189  std::unique_lock<std::mutex> lock(m_mutex);
190  while(m_size == m_capacity)
191  {
192  m_full_condition.wait(lock);
193  }
194  }
195  else
196  {
197  std::lock_guard<std::mutex> lock(m_mutex);
198  if(m_size == m_capacity)
199  {
200  return false;
201  }
202  }
203 
204  m_buffer[m_tail] = value;
205  m_tail = (m_tail + 1) % m_capacity;
206  ++m_size;
207 
208  m_empty_condition.notify_one();
209  return true;
210  }
211 
215  inline bool push(T&& value, bool block = true)
216  {
217  if(block)
218  {
219  std::unique_lock<std::mutex> lock(m_mutex);
220  while(m_size == m_capacity)
221  {
222  m_full_condition.wait(lock);
223  }
224  }
225  else
226  {
227  std::lock_guard<std::mutex> lock(m_mutex);
228  if(m_size == m_capacity)
229  {
230  return false;
231  }
232  }
233 
234  m_buffer[m_tail] = std::move(value);
235  m_tail = (m_tail + 1) % m_capacity;
236  ++m_size;
237 
238  m_empty_condition.notify_one();
239  return true;
240  }
241 
245  inline bool pop(T& value, bool block = true)
246  {
247  if(block)
248  {
249  std::unique_lock<std::mutex> lock(m_mutex);
250  while(m_size == 0)
251  {
252  m_empty_condition.wait(lock);
253  }
254  }
255  else
256  {
257  std::lock_guard<std::mutex> lock(m_mutex);
258  if(m_size == 0)
259  {
260  return false;
261  }
262  }
263 
264  value = std::move(m_buffer[m_head]);
265  m_head = (m_head + 1) % m_capacity;
266  --m_size;
267 
268  m_full_condition.notify_one();
269  return true;
270  }
271 
272 private:
273  const size_t m_capacity;
274  size_t m_size, m_head, m_tail;
275  T* m_buffer;
276  std::mutex m_mutex;
277  std::condition_variable m_full_condition;
278  std::condition_variable m_empty_condition;
279 #endif
280 };
281 
282 #endif // TTKCONCURRENTQUEUE_H
#define T(v)
Definition: http_parser.c:237
std::queue< T > m_queue
The class of the concurrent queue.
TTKConcurrentQueue() noexcept
void swap(TTKAny &left, TTKAny &right) noexcept
Definition: ttkany.h:224
void push(const T &value)
bool pop(T &value, bool block=true)
std::condition_variable m_condition
size_t size() const
#define const
Definition: zconf.h:233