TTKMusicPlayer  4.1.3.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 
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  }
132  {
133  delete[] m_buffer;
134  }
135 
139  inline size_t size() const
140  {
141  std::lock_guard<std::mutex> lock(m_mutex);
142  return m_size;
143  }
144 
148  inline bool empty() const
149  {
150  std::lock_guard<std::mutex> lock(m_mutex);
151  return m_size == 0;
152  }
153 
157  inline bool full() const
158  {
159  std::lock_guard<std::mutex> lock(m_mutex);
160  return m_size == m_capacity;
161  }
162 
166  inline size_t capacity() const
167  {
168  return m_capacity;
169  }
170 
174  inline void clear()
175  {
176  std::lock_guard<std::mutex> lock(m_mutex);
177  m_size = m_head = m_tail = 0;
178  memset(m_buffer, 0, sizeof(T) * m_capacity);
179  }
180 
184  inline bool push(const T& value, bool block = true)
185  {
186  if(block)
187  {
188  std::unique_lock<std::mutex> lock(m_mutex);
189  while(m_size == m_capacity)
190  {
191  m_full_condition.wait(lock);
192  }
193  }
194  else
195  {
196  std::lock_guard<std::mutex> lock(m_mutex);
197  if(m_size == m_capacity)
198  {
199  return false;
200  }
201  }
202 
203  m_buffer[m_tail] = value;
204  m_tail = (m_tail + 1) % m_capacity;
205  ++m_size;
206 
207  m_empty_condition.notify_one();
208  return true;
209  }
210 
214  inline bool push(T&& value, bool block = true)
215  {
216  if(block)
217  {
218  std::unique_lock<std::mutex> lock(m_mutex);
219  while(m_size == m_capacity)
220  {
221  m_full_condition.wait(lock);
222  }
223  }
224  else
225  {
226  std::lock_guard<std::mutex> lock(m_mutex);
227  if(m_size == m_capacity)
228  {
229  return false;
230  }
231  }
232 
233  m_buffer[m_tail] = std::move(value);
234  m_tail = (m_tail + 1) % m_capacity;
235  ++m_size;
236 
237  m_empty_condition.notify_one();
238  return true;
239  }
240 
244  inline bool pop(T& value, bool block = true)
245  {
246  if(block)
247  {
248  std::unique_lock<std::mutex> lock(m_mutex);
249  while(m_size == 0)
250  {
251  m_empty_condition.wait(lock);
252  }
253  }
254  else
255  {
256  std::lock_guard<std::mutex> lock(m_mutex);
257  if(m_size == 0)
258  {
259  return false;
260  }
261  }
262 
263  value = std::move(m_buffer[m_head]);
264  m_head = (m_head + 1) % m_capacity;
265  --m_size;
266 
267  m_full_condition.notify_one();
268  return true;
269  }
270 
271 private:
272  const size_t m_capacity;
273  size_t m_size, m_head, m_tail;
274  T* m_buffer;
275  std::mutex m_mutex;
276  std::condition_variable m_full_condition;
277  std::condition_variable m_empty_condition;
278 #endif
279 };
280 
281 #endif // TTKCONCURRENTQUEUE_H
#define T(v)
Definition: http_parser.c:237
std::queue< T > m_queue
The class of the concurrent queue.
void swap(TTKAny &left, TTKAny &right) noexcept
Definition: ttkany.h:212
void push(const T &value)
bool pop(T &value, bool block=true)
std::condition_variable m_condition
size_t size() const