libDwm-0.6.0
DwmThreadQueue.hh
Go to the documentation of this file.
1 //===========================================================================
2 // @(#) $DwmPath: dwm/libDwm/tags/libDwm-0.6.0/include/DwmThreadQueue.hh 8401 $
3 // @(#) $Id: DwmThreadQueue.hh 8401 2016-04-17 06:44:31Z dwm $
4 //===========================================================================
5 // Copyright (c) Daniel W. McRobb 2000-2007, 2016
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // 1. Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // 2. Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // 3. The names of the authors and copyright holders may not be used to
18 // endorse or promote products derived from this software without
19 // specific prior written permission.
20 //
21 // IN NO EVENT SHALL DANIEL W. MCROBB BE LIABLE TO ANY PARTY FOR
22 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
23 // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE,
24 // EVEN IF DANIEL W. MCROBB HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
25 // DAMAGE.
26 //
27 // THE SOFTWARE PROVIDED HEREIN IS ON AN "AS IS" BASIS, AND
28 // DANIEL W. MCROBB HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
29 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. DANIEL W. MCROBB MAKES NO
30 // REPRESENTATIONS AND EXTENDS NO WARRANTIES OF ANY KIND, EITHER
31 // IMPLIED OR EXPRESS, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,
33 // OR THAT THE USE OF THIS SOFTWARE WILL NOT INFRINGE ANY PATENT,
34 // TRADEMARK OR OTHER RIGHTS.
35 //===========================================================================
36 
37 //---------------------------------------------------------------------------
40 //---------------------------------------------------------------------------
41 
42 #ifndef _DWMTHREADQUEUE_HH_
43 #define _DWMTHREADQUEUE_HH_
44 
45 #include <deque>
46 #include <iostream>
47 #include <mutex>
48 #include <condition_variable>
49 
50 #include "DwmSysLogger.hh"
51 
52 using std::deque;
53 
54 namespace Dwm {
55 
56  namespace Thread {
57 
58  //------------------------------------------------------------------------
68  //------------------------------------------------------------------------
69  template <typename _ValueType>
70  class Queue
71  {
72  public:
73  //----------------------------------------------------------------------
75  //----------------------------------------------------------------------
77  : _maxLength(0), _queue(), _mutex(), _lock(_mutex), _cv()
78  {
79  _lock.unlock();
80  }
81 
82  //----------------------------------------------------------------------
84  //----------------------------------------------------------------------
86  {
87  std::unique_lock<std::mutex> lk(_mutex);
88  _queue.clear();
89  }
90 
91  //----------------------------------------------------------------------
94  //----------------------------------------------------------------------
95  uint32_t MaxLength() const
96  {
97  return(_maxLength);
98  }
99 
100  //----------------------------------------------------------------------
103  //----------------------------------------------------------------------
104  uint32_t MaxLength(uint32_t maxLength)
105  {
106  _maxLength = maxLength;
107  return(_maxLength);
108  }
109 
110  //----------------------------------------------------------------------
112  //----------------------------------------------------------------------
113  typename std::deque<_ValueType>::size_type Length() const
114  {
115  std::lock_guard<std::mutex> lk(_mutex);
116  return _queue.size();
117  }
118 
119  //----------------------------------------------------------------------
122  //----------------------------------------------------------------------
123  bool PushBack(const _ValueType & value)
124  {
125  bool rc = false;
126  std::lock_guard<std::mutex> lk(_mutex);
127  if ((! _maxLength) ||
128  (_queue.size() < _maxLength)) {
129  _queue.push_back(value);
130  _cv.notify_all();
131  rc = true;
132  }
133  return(rc);
134  }
135 
136  //----------------------------------------------------------------------
141  //----------------------------------------------------------------------
142  template <typename InputIterator>
143  uint32_t PushBack(InputIterator firstIter, InputIterator lastIter)
144  {
145  uint32_t rc = 0;
146  if (firstIter != lastIter) {
147  std::lock_guard<std::mutex> lk(_mutex);
148  if ((! _maxLength) ||
149  (_queue.size() < _maxLength)) {
150  uint32_t oldSize = _queue.size();
151  _queue.insert(_queue.end(), firstIter, lastIter);
152  rc = _queue.size() - oldSize;
153  if (rc) {
154  _cv.notify_all();
155  }
156  }
157  }
158  return(rc);
159  }
160 
161  //----------------------------------------------------------------------
164  //----------------------------------------------------------------------
165  bool PushFront(const _ValueType & value)
166  {
167  bool rc = false;
168  std::lock_guard<std::mutex> lk(_mutex);
169  if ((! _maxLength) ||
170  (_queue.size() < _maxLength)) {
171  _queue.push_front(value);
172  _cv.notify_all();
173  rc = true;
174  }
175  return(rc);
176  }
177 
178  //----------------------------------------------------------------------
180  //----------------------------------------------------------------------
182  {
183  _cv.notify_one();
184  }
185 
186  //----------------------------------------------------------------------
188  //----------------------------------------------------------------------
190  {
191  bool rc = false;
192  Lock();
193  rc = _cv.wait(_lock);
194  Unlock();
195  return(rc);
196  }
197 
198  //----------------------------------------------------------------------
202  //----------------------------------------------------------------------
203  template<class Rep, class Period>
204  bool ConditionTimedWait(const std::chrono::duration<Rep,Period> & timeToWait)
205  {
206  bool rc = false;
207  Lock();
208  if (_cv.wait_for(_lock, timeToWait) == std::cv_status::no_timeout) {
209  rc = true;
210  }
211  Unlock();
212  return(rc);
213  }
214 
215  //----------------------------------------------------------------------
218  //----------------------------------------------------------------------
219  bool PopFront(_ValueType & value)
220  {
221  bool rc = false;
222  std::lock_guard<std::mutex> lk(_mutex);
223  if (! _queue.empty()) {
224  value = _queue.front();
225  _queue.pop_front();
226  rc = true;
227  }
228  return(rc);
229  }
230 
231  //----------------------------------------------------------------------
234  //----------------------------------------------------------------------
235  bool PopBack(_ValueType & value)
236  {
237  bool rc = false;
238  std::lock_guard<std::mutex> lk(_mutex);
239  if (! _queue.empty()) {
240  value = _queue.back();
241  _queue.pop_back();
242  rc = true;
243  }
244  return(rc);
245  }
246 
247  //----------------------------------------------------------------------
250  //----------------------------------------------------------------------
252  {
253  bool rc = false;
254  Lock();
255  while (_queue.empty()) {
256  _cv.wait(_lock);
257  }
258  rc = true;
259  Unlock();
260  return(rc);
261  }
262 
263  //----------------------------------------------------------------------
266  //----------------------------------------------------------------------
267  template <class Rep, class Period>
268  bool TimedWaitForNotEmpty(const std::chrono::duration<Rep, Period> & timeToWait)
269  {
270  bool rc = false;
271  if (_queue.empty()) {
272  if (ConditionTimedWait(timeToWait)) {
273  if (! _queue.empty()) {
274  rc = true;
275  }
276  }
277  }
278  else {
279  rc = true;
280  }
281  return(rc);
282  }
283 
284  //----------------------------------------------------------------------
286  //----------------------------------------------------------------------
287  bool Empty()
288  {
289  return(_queue.empty());
290  }
291 
292  //----------------------------------------------------------------------
294  //----------------------------------------------------------------------
295  void RandomShuffle()
296  {
297  std::lock_guard<std::mutex> lk(_mutex);
298  random_shuffle(_queue.begin(), _queue.end());
299  return;
300  }
301 
302  //----------------------------------------------------------------------
307  //----------------------------------------------------------------------
308  uint32_t Copy(std::deque<_ValueType> & c)
309  {
310  uint32_t rc = 0;
311  if (! c.empty())
312  c.clear();
313 
314  std::lock_guard<std::mutex> lk(_mutex);
315  typename std::deque<_ValueType>::iterator iter = _queue.begin();
316  for ( ; iter != _queue.end(); ++iter) {
317  c.push_back(*iter);
318  ++rc;
319  }
320  return(rc);
321  }
322 
323  //----------------------------------------------------------------------
330  //----------------------------------------------------------------------
331  uint32_t Swap(std::deque<_ValueType> & c)
332  {
333  std::lock_guard<std::mutex> lk(_mutex);
334  if (! _queue.empty()) {
335  _queue.swap(c);
336  _queue.clear();
337  }
338  return(c.size());
339  }
340 
341  protected:
342  uint32_t _maxLength;
343  std::deque<_ValueType> _queue;
344  mutable std::mutex _mutex;
345  std::unique_lock<std::mutex> _lock;
346  std::condition_variable _cv;
347 
348  //----------------------------------------------------------------------
350  //----------------------------------------------------------------------
351  void Lock()
352  {
353  _lock.lock();
354  return;
355  }
356 
357  //----------------------------------------------------------------------
359  //----------------------------------------------------------------------
360  void Unlock()
361  {
362  _lock.unlock();
363  return;
364  }
365 
366  };
367 
368 
369  } // namespace Thread
370 
371 } // namespace Dwm
372 
373 #endif // _DWMTHREADQUEUE_HH_
374 
375 //---------------------------- emacs settings -----------------------------
376 // Local Variables:
377 // mode: C++
378 // tab-width: 2
379 // indent-tabs-mode: nil
380 // c-basic-offset: 2
381 // End:
382 //-------------------------------------------------------------------------
bool PushBack(const _ValueType &value)
Inserts value on the back of the queue.
Definition: DwmThreadQueue.hh:123
void ConditionSignal()
Unblocks at least one thread waiting on the condition variable.
Definition: DwmThreadQueue.hh:181
uint32_t Swap(std::deque< _ValueType > &c)
This member is a simple optimization for fetching the contents of the queue.
Definition: DwmThreadQueue.hh:331
uint32_t Copy(std::deque< _ValueType > &c)
Copies the contents of the queue to c.
Definition: DwmThreadQueue.hh:308
bool ConditionWait()
Waits for the condition variable to be signalled or broadcasted.
Definition: DwmThreadQueue.hh:189
Dwm::SysLogger class definition and Syslog() macro.
bool WaitForNotEmpty()
Blocks the calling thread until the queue contains at least one entry.
Definition: DwmThreadQueue.hh:251
bool PushFront(const _ValueType &value)
Inserts value on the front of the queue.
Definition: DwmThreadQueue.hh:165
Queue()
Constructor.
Definition: DwmThreadQueue.hh:76
uint32_t PushBack(InputIterator firstIter, InputIterator lastIter)
Inserts the values from firstIter to lastIter on the back of the queue.
Definition: DwmThreadQueue.hh:143
uint32_t MaxLength() const
Returns the max length of the queue.
Definition: DwmThreadQueue.hh:95
Definition: DwmBZ2IO.hh:67
~Queue()
Destructor.
Definition: DwmThreadQueue.hh:85
This template provides inter-thread first-in first-out (FIFO) queueing.
Definition: DwmThreadQueue.hh:70
bool PopBack(_ValueType &value)
Pops the entry from the back of the queue and stores it in value.
Definition: DwmThreadQueue.hh:235
uint32_t MaxLength(uint32_t maxLength)
Sets and returns the max length of the queue.
Definition: DwmThreadQueue.hh:104
std::deque< _ValueType >::size_type Length() const
Returns the current length of the queue.
Definition: DwmThreadQueue.hh:113
bool PopFront(_ValueType &value)
Pops the entry from the front of the queue and stores it in value.
Definition: DwmThreadQueue.hh:219
bool ConditionTimedWait(const std::chrono::duration< Rep, Period > &timeToWait)
Waits for the condition variable to be signalled or broadcasted for timeToWait to pass...
Definition: DwmThreadQueue.hh:204
bool Empty()
Returns true if the queue is empty, else returns false.
Definition: DwmThreadQueue.hh:287
bool TimedWaitForNotEmpty(const std::chrono::duration< Rep, Period > &timeToWait)
Waits timeToWait for the queue to be non-empty.
Definition: DwmThreadQueue.hh:268