c++-gtk-utils
async_queue.h
Go to the documentation of this file.
1 /* Copyright (C) 2006 to 2013 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36 
37 */
38 
39 /**
40  * @file async_queue.h
41  * @brief This file provides thread-safe asynchronous queue classes.
42  *
43  * AsyncQueue is a class which provides some of the functionality of a
44  * std::queue object (but note that the AsyncQueue::pop(value_type&
45  * obj) and AsyncQueue::move_pop(value_type& obj) methods provide the
46  * popped element by reference - see the comments on that method for
47  * the reason), except that it has mutex locking of the data container
48  * so as to permit pushing and popping from different threads. It is
49  * therefore useful for passing data between threads, perhaps in
50  * response to a signal being emitted from a Notifier object. Data
51  * can be pushed or pulled by move constructor/move assignment
52  * operator or by means of a std::unique_ptr object, SharedLockPtr
53  * object or an IntrusivePtr object referencing data derived from
54  * IntrusiveLockCounter.
55  *
56  * AsyncQueueDispatch is a class which has blocking pop() and
57  * move_pop() methods, which allows it to be waited on by a dedicated
58  * event/message dispatching thread for incoming work (represented by
59  * the data pushed onto the queue). In the same way, it can be used
60  * to implement thread pools, by having threads in the pool waiting on
61  * the queue.
62  *
63  * By default the queues use a std::list object as their container
64  * because when adding an item to the queue all allocation can take
65  * place outside the queue object's mutex. However, for types which
66  * have low overhead copy or move constructors, this can be changed
67  * to, say, a std::deque object by specifying it as the second
68  * template parameter.
69  */
70 
71 #ifndef CGU_ASYNC_QUEUE_H
72 #define CGU_ASYNC_QUEUE_H
73 
74 #include <queue>
75 #include <list>
76 #include <exception>
77 #include <utility> // for std::move and std::forward
78 #include <algorithm> // for std::swap
79 #include <time.h>
80 
81 #include <c++-gtk-utils/mutex.h>
82 #include <c++-gtk-utils/thread.h>
84 
85 #ifdef CGU_USE_SCHED_YIELD
86 #include <sched.h>
87 #else
88 #include <unistd.h>
89 #endif
90 
91 namespace Cgu {
92 
93 /**
94  * @class AsyncQueuePopError async_queue.h c++-gtk-utils/async_queue.h
95  * @brief An exception thrown if calling pop() on a AsyncQueue or
96  * AsyncQueueDispatch object fails because the queue is empty.
97  * @sa AsyncQueue AsyncQueueDispatch
98  */
99 
100 struct AsyncQueuePopError: public std::exception {
101  virtual const char* what() const throw() {return "AsyncQueuePopError: popping from empty AsyncQueue object\n";}
102 };
103 
104 
105 /**
106  * @class AsyncQueue async_queue.h c++-gtk-utils/async_queue.h
107  * @brief A thread-safe asynchronous queue.
108  * @sa AsyncQueueDispatch AsyncResult
109  *
110  * AsyncQueue is a class which provides some of the functionality of a
111  * std::queue object (but note that the AsyncQueue::pop(value_type&
112  * obj) and AsyncQueue::move_pop(value_type& obj) methods provide the
113  * popped element by reference - see the comments on that method for
114  * the reason), except that it has mutex locking of the data container
115  * so as to permit pushing and popping from different threads. It is
116  * therefore useful for passing data between threads, perhaps in
117  * response to a signal being emitted from a Notifier object. Data
118  * can be pushed or pulled by move constructor/move assignment
119  * operator or by means of a std::unique_ptr object, SharedLockPtr
120  * object or an IntrusivePtr object referencing data derived from
121  * IntrusiveLockCounter.
122  *
123  * By default the queue uses a std::list object as its container
124  * because when adding an item to the queue all allocation can take
125  * place outside the queue object's mutex. However, for types which
126  * have low overhead copy or move constructors, this can be changed
127  * to, say, a std::deque object by specifying it as the second
128  * template parameter.
129  *
130  * If the library is installed using the
131  * \--with-glib-memory-slices-compat or
132  * \--with-glib-memory-slices-no-compat configuration options, any
133  * AsyncQueue objects constructed on free store will be constructed in
134  * glib memory slices. This does not affect the queue container
135  * itself: to change the allocator of the C++ container, a custom
136  * allocator type can be provided when the AsyncQueue object is
137  * instantiated offering the standard allocator interface. If glib
138  * memory slices are not used or no AsyncQueue objects are constructed
139  * on free store, it is not necessary to call g_thread_init() before
140  * manipulating or using an AsyncQueue object in multiple threads, but
141  * prior to glib version 2.32 glib itself (and thus glib memory
142  * slices) are not thread safe unless that function has been called.
143  */
144 
145 template <class T, class Container = std::list<T> > class AsyncQueue {
146 public:
147  typedef typename Container::value_type value_type;
148  typedef typename Container::size_type size_type;
149  typedef Container container_type;
150 private:
151  mutable Thread::Mutex mutex;
152  std::queue<T, Container> q;
153 
154 // this won't throw: it is for the user to ensure the arguments do not
155 // refer to the same mutex object
156  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
157  m1.lock();
158  for(;;) {
159  if (!m2.trylock()) {
160  return;
161  }
162  m1.unlock();
163  // spin nicely
164 #ifdef CGU_USE_SCHED_YIELD
165  sched_yield();
166 #else
167  usleep(10);
168 #endif
169  m1.lock();
170  }
171  }
172 public:
173 /**
174  * Pushes an item onto the queue. This method has strong exception
175  * safety if the container is a std::list or std::deque container (the
176  * default is std::list), except that if std::deque is used as the
177  * container and the copy constructor, move constructor, copy
178  * assignment operator or move assignment operator of the queue item
179  * throws, it only gives the basic exception guarantee (and the basic
180  * guarantee is not given by std::deque if the queue item's move
181  * constructor throws and it uses a non-default allocator which does
182  * not provide for it to be CopyInsertable). It is thread safe.
183  * @param obj The item to be pushed onto the queue.
184  * @exception std::bad_alloc The method might throw std::bad_alloc if
185  * memory is exhausted and the system throws in that case. It might
186  * also throw if the copy constructor, move constructor, assignment
187  * operator or move assignment operator of the queue item might throw.
188  */
189  void push(const value_type& obj) {
190  Thread::Mutex::Lock lock{mutex};
191  q.push(obj);
192  }
193 
194 /**
195  * Pushes an item onto the queue. This method has strong exception
196  * safety if the container is a std::list or std::deque container (the
197  * default is std::list), except that if std::deque is used as the
198  * container and the copy constructor, move constructor, copy
199  * assignment operator or move assignment operator of the queue item
200  * throws, it only gives the basic exception guarantee (and the basic
201  * guarantee is not given by std::deque if the queue item's move
202  * constructor throws and it uses a non-default allocator which does
203  * not provide for it to be CopyInsertable). It is thread safe.
204  * @param obj The item to be pushed onto the queue.
205  * @exception std::bad_alloc The method might throw std::bad_alloc if
206  * memory is exhausted and the system throws in that case. It might
207  * also throw if the copy constructor, move constructor, assignment
208  * operator or move assignment operator of the queue item might throw.
209  *
210  * Since 2.0.0-rc5
211  */
212  void push(value_type&& obj) {
213  Thread::Mutex::Lock lock{mutex};
214  q.push(std::move(obj));
215  }
216 
217 /**
218  * Pushes an item onto the queue by constructing it in place: that is,
219  * by passing to this method the item's constructor's arguments,
220  * rather than the item itself. This method has strong exception
221  * safety if the container is a std::list or std::deque container (the
222  * default is std::list). (Technically, for a std::deque container,
223  * emplace() only offers the same exception guarantees as does push(),
224  * namely only the basic guarantee where a copy or move of the queue
225  * item throws during the call, but the purpose of emplace is to
226  * construct in place and any reasonable implementation will not copy
227  * or move the queue item.) It is thread safe.
228  * @param args The constructor arguments for the item to be pushed
229  * onto the queue.
230  * @exception std::bad_alloc The method might throw std::bad_alloc if
231  * memory is exhausted and the system throws in that case. It might
232  * also throw if the item's constructor (including any of its
233  * constructor arguments) might throw when constructing the item.
234  * @note The constructor of the item pushed onto the queue must not
235  * access any of the methods of the same queue object, or a deadlock
236  * might occur.
237  *
238  * Since 2.0.0-rc5
239  */
240  template<class... Args>
241  void emplace(Args&&... args) {
242  Thread::Mutex::Lock lock{mutex};
243  q.emplace(std::forward<Args>(args)...);
244  }
245 
246 /**
247  * Pops an item from the queue. This method has strong exception
248  * safety if the container is a std::deque or std::list container (the
249  * default is std::list), provided the destructor of a contained item
250  * does not throw. It is thread safe.
251  * @param obj A value type reference to which the item at the front of
252  * the queue will be assigned.
253  * @exception AsyncQueuePopError If the queue is empty when a pop is
254  * attempted, this method will throw AsyncQueuePopError. It might
255  * also throw if the copy assignment operator of the queue item might
256  * throw. In order to complete pop operations atomically under a
257  * single lock and to retain strong exception safety, the object into
258  * which the popped data is to be placed is passed as an argument by
259  * reference (this avoids a copy from a temporary object after the
260  * data has been extracted from the queue, which would occur if the
261  * item extracted were returned by value). It might also throw if the
262  * destructor of the queue item might throw (but that should never
263  * happen), or if the empty() method of the container type throws
264  * (which would not happen on any sane implementation).
265  */
266  void pop(value_type& obj) {
267  Thread::Mutex::Lock lock{mutex};
268  if (q.empty()) throw AsyncQueuePopError();
269  obj = q.front();
270  q.pop();
271  }
272 
273 /**
274  * Pops an item from the queue using the contained type's move
275  * assignment operator, if it has one. This method is identical to
276  * the pop() method if that type has no move assignment operator.
277  * This method has strong exception safety if the container is a
278  * std::deque or std::list container (the default is std::list),
279  * provided the destructor of a contained item does not throw and the
280  * move assignment operator of a contained item has strong exception
281  * safety. It is thread safe. Use this method in preference to the
282  * pop() method if it is known that the contained items' move
283  * assignment operator does not throw or is strongly exception safe,
284  * or if the use case does not require strong exception safety. This
285  * method must be used in place of the pop() method if the contained
286  * type has a move assignment operator but no copy assignment operator
287  * (such as a std::unique_ptr object).
288  * @param obj A value type reference to which the item at the front of
289  * the queue will be move assigned.
290  * @exception AsyncQueuePopError If the queue is empty when a pop is
291  * attempted, this method will throw AsyncQueuePopError. It might
292  * also throw if the move assignment operator of the queue item might
293  * throw, or if it has no move assignment operator and its copy
294  * assignment operator throws. In order to complete pop operations
295  * atomically under a single lock and to retain strong exception
296  * safety, the object into which the popped data is to be placed is
297  * passed as an argument by reference (this avoids a move from a
298  * temporary object after the data has been extracted from the queue,
299  * which would occur if the item extracted were returned by value).
300  * It might also throw if the destructor of the queue item might throw
301  * (but that should never happen), or if the empty() method of the
302  * container type throws (which would not happen on any sane
303  * implementation).
304  *
305  * Since 2.0.11
306  */
307  void move_pop(value_type& obj) {
308  Thread::Mutex::Lock lock{mutex};
309  if (q.empty()) throw AsyncQueuePopError();
310  obj = std::move(q.front());
311  q.pop();
312  }
313 
314 /**
315  * Discards the item at the front of the queue. This method has
316  * strong exception safety if the container is a std::deque or
317  * std::list container (the default is std::list), provided the
318  * destructor of a contained item does not throw. It is thread safe.
319  * @exception AsyncQueuePopError If the queue is empty when a pop is
320  * attempted, this method will throw AsyncQueuePopError. It might
321  * also throw if the destructor of the queue item might throw (but
322  * that should never happen), or if the empty() method of the
323  * container type throws (which would not happen on any sane
324  * implementation).
325  */
326  void pop() {
327  Thread::Mutex::Lock lock{mutex};
328  if (q.empty()) throw AsyncQueuePopError();
329  q.pop();
330  }
331 
332 /**
333  * @return Whether the queue is empty. It will not throw assuming
334  * that the empty() method of the container type does not throw, as it
335  * will not on any sane implementation.
336  * @note This method is thread safe, but the return value may not be
337  * valid if another thread has pushed to or popped from the queue
338  * before the value returned by the method is acted on. It is
339  * provided as a utility, but may not be meaningful, depending on the
340  * intended usage.
341  */
342  bool empty() const {
343  Thread::Mutex::Lock lock{mutex};
344  return q.empty();
345  }
346 
347 /**
348  * @return The number of items currently in the queue. It will not
349  * throw assuming that the size() method of the container type does
350  * not throw, as it will not on any sane implementation.
351  * @note This method is thread safe, but the return value may not be
352  * valid if another thread has pushed to or popped from the queue
353  * before the value returned by the method is acted on. It is
354  * provided as a utility, but may not be meaningful, depending on the
355  * intended usage.
356  *
357  * Since 2.0.8
358  */
359  size_type size() const {
360  Thread::Mutex::Lock lock{mutex};
361  return q.size();
362  }
363 
364 /**
365  * Swaps the contents of 'this' and 'other'. It will not throw
366  * assuming that the swap method of the container type does not throw
367  * (which the C++11 standard requires not to happen with the standard
368  * sequence containers). It is thread safe and the swap is
369  * thread-wise atomic. A non-class function
370  * Cgu::swap(Cgu::AsyncQueue&, Cgu::AsyncQueue&) method is also
371  * provided which will call this method.
372  * @param other The object to be swapped with this one.
373  *
374  * Since 2.0.8
375  */
376  void swap(AsyncQueue& other) {
377  if (this != &other) {
378  lock2(mutex, other.mutex); // doesn't throw
380  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
381  q.swap(other.q);
382  }
383  }
384 
385 /**
386  * The copy assignment operator is strongly exception safe with the
387  * standard sequence containers (it uses copy and swap). It is also
388  * thread safe, as it safely locks both the assignor's and assignee's
389  * mutex to provide a thread-wise atomic assignment.
390  * @param rhs The assignor.
391  * @return The AsyncQueue object after assignment.
392  * @exception std::bad_alloc The copy constructor of the queue's
393  * container type, and so this assignment operator, might throw
394  * std::bad_alloc if memory is exhausted and the system throws in that
395  * case. This assignment operator will also throw if the copy
396  * constructor of the queue's container type throws any other
397  * exceptions, including if any copy or move constructor or copy or
398  * move assignment operator of a contained item throws.
399  * @exception Thread::MutexError This assignment operator might throw
400  * Thread::MutexError if initialization of a transitional object's
401  * contained mutex fails. (It is often not worth checking for this,
402  * as it means either memory is exhausted or pthread has run out of
403  * other resources to create new mutexes.)
404  *
405  * Since 2.0.8
406  */
408  if (this != &rhs) {
409  lock2(mutex, rhs.mutex); // doesn't throw
411  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
412  std::queue<T, Container> temp{rhs.q};
413  q.swap(temp);
414  }
415  return *this;
416  }
417 
418 /**
419  * This move assignment operator is thread safe as regards the
420  * assignee (the object moved to), but no synchronization is carried
421  * out with respect to the rvalue assignor/movant. This is because
422  * temporaries are only visible and accessible in the thread carrying
423  * out the move operation and synchronization for them would represent
424  * pointless overhead. In a case where the user uses std::move to
425  * force a move from a named object, and that named object's lifetime
426  * is managed by (or the object is otherwise accessed by) a different
427  * thread than the one making the move, the user must carry out her
428  * own synchronization with respect to that different thread, both to
429  * ensure that a consistent view of the the named object is obtained
430  * and because that object will be mutated by the move. This method
431  * invokes std::queue's move assignment operator, and therefore has
432  * the same exception safety as the standard library's implementation
433  * of that operator. It will not normally throw unless a custom
434  * allocator is used which throws on move assignment, or the
435  * destructor of a contained item throws.
436  * @param rhs The assignor/movant.
437  * @return The AsyncQueue object after move assignment.
438  *
439  * Since 2.0.8
440  */
442  Thread::Mutex::Lock lock{mutex};
443  q = std::move(rhs.q);
444  return *this;
445  }
446 
447 /**
448  * @exception std::bad_alloc The default constructor might throw
449  * std::bad_alloc if memory is exhausted and the system throws in that
450  * case.
451  * @exception Thread::MutexError The default constructor might throw
452  * Thread::MutexError if initialization of the contained mutex fails.
453  * (It is often not worth checking for this, as it means either memory
454  * is exhausted or pthread has run out of other resources to create
455  * new mutexes.)
456  */
457  AsyncQueue() = default;
458 
459 /**
460  * As regards thread safety, the move constructor does not synchronize
461  * with respect to the initializing rvalue. This is because
462  * temporaries are only visible and accessible in the thread carrying
463  * out the move operation and synchronization for them would represent
464  * pointless overhead. In a case where a user uses std::move to force
465  * a move from a named object, and that named object's lifetime is
466  * managed by (or the object is otherwise accessed by) a different
467  * thread than the one making the move, the user must carry out her
468  * own synchronization with respect to that different thread, both to
469  * ensure that a consistent view of the the named object is obtained
470  * and because that object will be mutated by the move.
471  * @param rhs The AsyncQueue object to be moved.
472  * @exception Thread::MutexError The move constructor might throw
473  * Thread::MutexError if initialization of the contained mutex fails.
474  * If it does so this move constructor is strongly exception safe (if
475  * it is thrown, the object passed as an argument will be unchanged).
476  * (It is often not worth checking for this, as it means either memory
477  * is exhausted or pthread has run out of other resources to create
478  * new mutexes.) It might also throw if the queue's container type's
479  * move constructor might throw, but it should not do that unless a
480  * custom allocator is in use.
481  *
482  * Since 2.0.8
483  */
484  AsyncQueue(AsyncQueue&& rhs): q(std::move(rhs.q)) {}
485 
486 /**
487  * The copy constructor is thread safe, as it locks the initializing
488  * object's mutex to obtain a consistent view of it.
489  * @param rhs The AsyncQueue object to be copied.
490  * @exception std::bad_alloc The copy constructor of the queue's
491  * container type, and so this constructor, might throw std::bad_alloc
492  * if memory is exhausted and the system throws in that case. It will
493  * also throw if the copy constructor of the queue's container type
494  * throws any other exceptions, including if any copy or move
495  * constructor or copy or move assignment operator of a contained item
496  * throws.
497  * @exception Thread::MutexError The copy constructor might throw
498  * Thread::MutexError if initialization of the contained mutex fails.
499  * (It is often not worth checking for this, as it means either memory
500  * is exhausted or pthread has run out of other resources to create
501  * new mutexes.)
502  *
503  * Since 2.0.8
504  */
505  // we use the comma operator here to lock the mutex and call the
506  // copy constructor: the lock will be retained until the end of the
507  // full expression in which it is lexically situated, namely until
508  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
509  AsyncQueue(const AsyncQueue& rhs): q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
510 
511 /**
512  * The destructor does not throw unless the destructor of a contained
513  * item throws. It is thread safe (any thread may delete the
514  * AsyncQueue object).
515  */
517  // lock and unlock the mutex in the destructor so that we have an
518  // acquire operation to ensure that when the std::queue object is
519  // destroyed memory is synchronised, so any thread may destroy the
520  // AsyncQueue object
521  Thread::Mutex::Lock lock{mutex};
522  }
523 
524 /* Only has effect if --with-glib-memory-slices-compat or
525  * --with-glib-memory-slices-no-compat option picked */
527 };
528 
529 /**
530  * @class AsyncQueueDispatch async_queue.h c++-gtk-utils/async_queue.h
531  * @brief A thread-safe asynchronous queue with a blocking pop()
532  * method.
533  * @sa AsyncQueue AsyncResult
534  *
535  * AsyncQueueDispatch is a class which has blocking pop_dispatch()
536  * and move_pop_dispatch() methods, which allows it to be waited on by a dedicated
537  * event/message dispatching thread for incoming work (represented by
538  * the data pushed onto the queue). In the same way, it can be used
539  * to implement thread pools, by having threads in the pool waiting on
540  * the queue. The AsyncResult class can be useful for passing results
541  * between threads in conjunction with AsyncQueueDispatch (the
542  * documentation on AsyncResult gives an example).
543  *
544  * By default the queue uses a std::list object as its container
545  * because when adding an item to the queue all allocation can take
546  * place outside the queue object's mutex. However, for types which
547  * have low overhead copy or move constructors, this can be changed
548  * to, say, a std::deque object by specifying it as the second
549  * template parameter.
550  *
551  * If the library is installed using the
552  * \--with-glib-memory-slices-compat or
553  * \--with-glib-memory-slices-no-compat configuration options, any
554  * AsyncQueueDispatch objects constructed on free store will be
555  * constructed in glib memory slices. This does not affect the queue
556  * container itself: to change the allocator of the C++ container, a
557  * custom allocator type can be provided when the AsyncQueueDispatch
558  * object is instantiated offering the standard allocator interface.
559  * If glib memory slices are not used or no AsyncQueueDispatch objects
560  * are constructed on free store, it is not necessary to call
561  * g_thread_init() before manipulating or using an AsyncQueueDispatch
562  * object in multiple threads, but prior to glib version 2.32 glib
563  * itself (and thus glib memory slices) are not thread safe unless
564  * that function has been called.
565  */
566 
567 template <class T, class Container = std::list<T> > class AsyncQueueDispatch {
568 public:
569  typedef typename Container::value_type value_type;
570  typedef typename Container::size_type size_type;
571  typedef Container container_type;
572 private:
573  mutable Thread::Mutex mutex;
574  Thread::Cond cond;
575  std::queue<T, Container> q;
576 
577 // this won't throw: it is for the user to ensure the arguments do not
578 // refer to the same mutex object
579  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
580  m1.lock();
581  for(;;) {
582  if (!m2.trylock()) {
583  return;
584  }
585  m1.unlock();
586  // spin nicely
587 #ifdef CGU_USE_SCHED_YIELD
588  sched_yield();
589 #else
590  usleep(10);
591 #endif
592  m1.lock();
593  }
594  }
595 public:
596 /**
597  * Pushes an item onto the queue. This method has strong exception
598  * safety if the container is a std::list or std::deque container (the
599  * default is std::list), except that if std::deque is used as the
600  * container and the copy constructor, move constructor, copy
601  * assignment operator or move assignment operator of the queue item
602  * throws, it only gives the basic exception guarantee (and the basic
603  * guarantee is not given by std::deque if the queue item's move
604  * constructor throws and it uses a non-default allocator which does
605  * not provide for it to be CopyInsertable). It is thread safe.
606  * @param obj The item to be pushed onto the queue.
607  * @exception std::bad_alloc The method might throw std::bad_alloc if
608  * memory is exhausted and the system throws in that case. It might
609  * also throw if the copy constructor, move constructor, assignment
610  * operator or move assignment operator of the queue item might throw.
611  */
612  void push(const value_type& obj) {
613  Thread::Mutex::Lock lock{mutex};
614  q.push(obj);
615  cond.signal();
616  }
617 
618 /**
619  * Pushes an item onto the queue. This method has strong exception
620  * safety if the container is a std::list or std::deque container (the
621  * default is std::list), except that if std::deque is used as the
622  * container and the copy constructor, move constructor, copy
623  * assignment operator or move assignment operator of the queue item
624  * throws, it only gives the basic exception guarantee (and the basic
625  * guarantee is not given by std::deque if the queue item's move
626  * constructor throws and it uses a non-default allocator which does
627  * not provide for it to be CopyInsertable). It is thread safe.
628  * @param obj The item to be pushed onto the queue.
629  * @exception std::bad_alloc The method might throw std::bad_alloc if
630  * memory is exhausted and the system throws in that case. It might
631  * also throw if the copy constructor, move constructor, assignment
632  * operator or move assignment operator of the queue item might throw.
633  *
634  * Since 2.0.0-rc5
635  */
636  void push(value_type&& obj) {
637  Thread::Mutex::Lock lock{mutex};
638  q.push(std::move(obj));
639  cond.signal();
640  }
641 
642 /**
643  * Pushes an item onto the queue by constructing it in place: that is,
644  * by passing to this method the item's constructor's arguments,
645  * rather than the item itself. This method has strong exception
646  * safety if the container is a std::list or std::deque container (the
647  * default is std::list). (Technically, for a std::deque container,
648  * emplace() only offers the same exception guarantees as does push(),
649  * namely only the basic guarantee where a copy or move of the queue
650  * item throws during the call, but the purpose of emplace is to
651  * construct in place and any reasonable implementation will not copy
652  * or move the queue item.) It is thread safe.
653  * @param args The constructor arguments for the item to be pushed
654  * onto the queue.
655  * @exception std::bad_alloc The method might throw std::bad_alloc if
656  * memory is exhausted and the system throws in that case. It might
657  * also throw if the item's constructor (including any of its
658  * constructor arguments) might throw when constructing the item.
659  * @note The constructor of the item pushed onto the queue must not
660  * access any of the methods of the same queue object, or a deadlock
661  * might occur.
662  *
663  * Since 2.0.0-rc5
664  */
665  template<class... Args>
666  void emplace(Args&&... args) {
667  Thread::Mutex::Lock lock{mutex};
668  q.emplace(std::forward<Args>(args)...);
669  cond.signal();
670  }
671 
672 /**
673  * Pops an item from the queue. This method has strong exception
674  * safety if the container is a std::deque or std::list container (the
675  * default is std::list), provided the destructor of a contained item
676  * does not throw. It is thread safe.
677  * @param obj A value type reference to which the item at the front of
678  * the queue will be assigned.
679  * @exception AsyncQueuePopError If the queue is empty when a pop is
680  * attempted, this method will throw AsyncQueuePopError. It might
681  * also throw if the copy assignment operator of the queue item might
682  * throw. In order to complete pop operations atomically under a
683  * single lock and to retain strong exception safety, the object into
684  * which the popped data is to be placed is passed as an argument by
685  * reference (this avoids a copy from a temporary object after the
686  * data has been extracted from the queue, which would occur if the
687  * item extracted were returned by value). It might also throw if the
688  * destructor of the queue item might throw (but that should never
689  * happen), or if the empty() method of the container type throws
690  * (which would not happen on any sane implementation).
691  */
692  void pop(value_type& obj) {
693  Thread::Mutex::Lock lock{mutex};
694  if (q.empty()) throw AsyncQueuePopError();
695  obj = q.front();
696  q.pop();
697  }
698 
699 /**
700  * Pops an item from the queue using the contained type's move
701  * assignment operator, if it has one. This method is identical to
702  * the pop() method if that type has no move assignment operator.
703  * This method has strong exception safety if the container is a
704  * std::deque or std::list container (the default is std::list),
705  * provided the destructor of a contained item does not throw and the
706  * move assignment operator of a contained item has strong exception
707  * safety. It is thread safe. Use this method in preference to the
708  * pop() method if it is known that the contained items' move
709  * assignment operator does not throw or is strongly exception safe,
710  * or if the use case does not require strong exception safety. This
711  * method must be used in place of the pop() method if the contained
712  * type has a move assignment operator but no copy assignment operator
713  * (such as a std::unique_ptr object).
714  * @param obj A value type reference to which the item at the front of
715  * the queue will be move assigned.
716  * @exception AsyncQueuePopError If the queue is empty when a pop is
717  * attempted, this method will throw AsyncQueuePopError. It might
718  * also throw if the move assignment operator of the queue item might
719  * throw, or if it has no move assignment operator and its copy
720  * assignment operator throws. In order to complete pop operations
721  * atomically under a single lock and to retain strong exception
722  * safety, the object into which the popped data is to be placed is
723  * passed as an argument by reference (this avoids a move from a
724  * temporary object after the data has been extracted from the queue,
725  * which would occur if the item extracted were returned by value).
726  * It might also throw if the destructor of the queue item might throw
727  * (but that should never happen), or if the empty() method of the
728  * container type throws (which would not happen on any sane
729  * implementation).
730  *
731  * Since 2.0.11
732  */
733  void move_pop(value_type& obj) {
734  Thread::Mutex::Lock lock{mutex};
735  if (q.empty()) throw AsyncQueuePopError();
736  obj = std::move(q.front());
737  q.pop();
738  }
739 
740 /**
741  * Pops an item from the queue. If the queue is empty, it will block
742  * until an item becomes available. If it blocks, the wait comprises
743  * a cancellation point. This method is cancellation safe if the
744  * stack unwinds on cancellation, as cancellation is blocked while the
745  * queue is being operated on after coming out of a wait. This method
746  * has strong exception safety if the container is a std::deque or
747  * std::list container (the default is std::list), provided the
748  * destructor of a contained item does not throw. It is thread safe.
749  * @param obj A value type reference to which the item at the front of
750  * the queue will be assigned. This method might throw if the copy
751  * assignment operator of the queue item might throw. In order to
752  * complete pop operations atomically under a single lock and to
753  * retain strong exception safety, the object into which the popped
754  * data is to be placed is passed as an argument by reference (this
755  * avoids a copy from a temporary object after the data has been
756  * extracted from the queue, which would occur if the item extracted
757  * were returned by value). It might also throw if the destructor of
758  * the queue item might throw (but that should never happen), or if
759  * the empty() method of the container type throws (which would not
760  * happen on any sane implementation).
761  */
763  Thread::Mutex::Lock lock{mutex};
764  while (q.empty()) cond.wait(mutex);
766  obj = q.front();
767  q.pop();
768  }
769 
770 /**
771  * Pops an item from the queue using the contained type's move
772  * assignment operator, if it has one (this method is identical to the
773  * pop_dispatch() method if that type has no move assignment
774  * operator). If the queue is empty, it will block until an item
775  * becomes available. If it blocks, the wait comprises a cancellation
776  * point. This method is cancellation safe if the stack unwinds on
777  * cancellation, as cancellation is blocked while the queue is being
778  * operated on after coming out of a wait. This method has strong
779  * exception safety if the container is a std::deque or std::list
780  * container (the default is std::list), provided the destructor of a
781  * contained item does not throw and the move assignment operator of a
782  * contained item has strong exception safety. It is thread safe.
783  * Use this method in preference to the pop_dispatch() method if it is
784  * known that the contained items' move assignment operator does not
785  * throw or is strongly exception safe, or if the use case does not
786  * require strong exception safety. This method must be used in place
787  * of the pop_dispatch() method if the contained type has a move
788  * assignment operator but no copy assignment operator (such as a
789  * std::unique_ptr object).
790  * @param obj A value type reference to which the item at the front of
791  * the queue will be move assigned. This method might throw if the
792  * move assignment operator of the queue item might throw, or if it
793  * has no move assignment operator and its copy assignment operator
794  * throws. In order to complete pop operations atomically under a
795  * single lock and to retain strong exception safety, the object into
796  * which the popped data is to be placed is passed as an argument by
797  * reference (this avoids a move from a temporary object after the
798  * data has been extracted from the queue, which would occur if the
799  * item extracted were returned by value). It might also throw if the
800  * destructor of the queue item might throw (but that should never
801  * happen), or if the empty() method of the container type throws
802  * (which would not happen on any sane implementation).
803  *
804  * Since 2.0.11
805  */
807  Thread::Mutex::Lock lock{mutex};
808  while (q.empty()) cond.wait(mutex);
810  obj = std::move(q.front());
811  q.pop();
812  }
813 
814 /**
815  * Pops an item from the queue. If the queue is empty, it will block
816  * until an item becomes available or until the timeout expires. If
817  * it blocks, the wait comprises a cancellation point. This method is
818  * cancellation safe if the stack unwinds on cancellation, as
819  * cancellation is blocked while the queue is being operated on after
820  * coming out of a wait. This method has strong exception safety if
821  * the container is a std::deque or std::list container (the default
822  * is std::list), provided the destructor of a contained item does not
823  * throw. It is thread safe.
824  * @param obj A value type reference to which the item at the front of
825  * the queue will be assigned. This method might throw if the copy
826  * assignment operator of the queue item might throw. In order to
827  * complete pop operations atomically under a single lock and to
828  * retain strong exception safety, the object into which the popped
829  * data is to be placed is passed as an argument by reference (this
830  * avoids a copy from a temporary object after the data has been
831  * extracted from the queue, which would occur if the item extracted
832  * were returned by value). It might also throw if the destructor of
833  * the queue item might throw (but that should never happen), or if
834  * the empty() method of the container type throws (which would not
835  * happen on any sane implementation).
836  * @param millisec The timeout interval, in milliseconds.
837  * @return If the timeout expires without an item becoming available,
838  * the method will return true. If an item from the queue is
839  * extracted, it returns false.
840  */
841  bool pop_timed_dispatch(value_type& obj, unsigned int millisec) {
842  timespec ts;
843  Thread::Cond::get_abs_time(ts, millisec);
844  Thread::Mutex::Lock lock{mutex};
845  while (q.empty()) {
846  if (cond.timed_wait(mutex, ts)) return true;
847  }
849  obj = q.front();
850  q.pop();
851  return false;
852  }
853 
854 /**
855  * Pops an item from the queue using the contained type's move
856  * assignment operator, if it has one (this method is identical to the
857  * pop_timed_dispatch() method if that type has no move assignment
858  * operator). If the queue is empty, it will block until an item
859  * becomes available or until the timeout expires. If it blocks, the
860  * wait comprises a cancellation point. This method is cancellation
861  * safe if the stack unwinds on cancellation, as cancellation is
862  * blocked while the queue is being operated on after coming out of a
863  * wait. This method has strong exception safety if the container is
864  * a std::deque or std::list container (the default is std::list),
865  * provided the destructor of a contained item does not throw and the
866  * move assignment operator of a contained item has strong exception
867  * safety. It is thread safe. Use this method in preference to the
868  * pop_timed_dispatch() method if it is known that the contained
869  * items' move assignment operator does not throw or is strongly
870  * exception safe, or if the use case does not require strong
871  * exception safety. This method must be used in place of the
872  * pop_timed_dispatch() method if the contained type has a move
873  * assignment operator but no copy assignment operator (such as a
874  * std::unique_ptr object).
875  * @param obj A value type reference to which the item at the front of
876  * the queue will be move assigned. This method might throw if the
877  * move assignment operator of the queue item might throw, or if it
878  * has no move assignment operator and its copy assignment operator
879  * throws. In order to complete pop operations atomically under a
880  * single lock and to retain strong exception safety, the object into
881  * which the popped data is to be placed is passed as an argument by
882  * reference (this avoids a move from a temporary object after the
883  * data has been extracted from the queue, which would occur if the
884  * item extracted were returned by value). It might also throw if the
885  * destructor of the queue item might throw (but that should never
886  * happen), or if the empty() method of the container type throws
887  * (which would not happen on any sane implementation).
888  * @param millisec The timeout interval, in milliseconds.
889  * @return If the timeout expires without an item becoming available,
890  * the method will return true. If an item from the queue is
891  * extracted, it returns false.
892  *
893  * Since 2.0.11
894  */
895  bool move_pop_timed_dispatch(value_type& obj, unsigned int millisec) {
896  timespec ts;
897  Thread::Cond::get_abs_time(ts, millisec);
898  Thread::Mutex::Lock lock{mutex};
899  while (q.empty()) {
900  if (cond.timed_wait(mutex, ts)) return true;
901  }
903  obj = std::move(q.front());
904  q.pop();
905  return false;
906  }
907 
908 /**
909  * Discards the item at the front of the queue. This method has
910  * strong exception safety if the container is a std::deque or
911  * std::list container (the default is std::list), provided the
912  * destructor of a contained item does not throw. It is thread safe.
913  * @exception AsyncQueuePopError If the queue is empty when a pop is
914  * attempted, this method will throw AsyncQueuePopError. It might
915  * also throw if the destructor of the queue item might throw (but
916  * that should never happen), or if the empty() method of the
917  * container type throws (which would not happen on any sane
918  * implementation).
919  */
920  void pop() {
921  Thread::Mutex::Lock lock{mutex};
922  if (q.empty()) throw AsyncQueuePopError();
923  q.pop();
924  }
925 
926 /**
927  * @return Whether the queue is empty. It will not throw assuming
928  * that the empty() method of the container type does not throw, as it
929  * will not on any sane implementation.
930  * @note This method is thread safe, but the return value may not be
931  * valid if another thread has pushed to or popped from the queue
932  * before the value returned by the method is acted on. It is
933  * provided as a utility, but may not be meaningful, depending on the
934  * intended usage.
935  */
936  bool empty() const {
937  Thread::Mutex::Lock lock{mutex};
938  return q.empty();
939  }
940 
941 /**
942  * @return The number of items currently in the queue. It will not
943  * throw assuming that the size() method of the container type does
944  * not throw, as it will not on any sane implementation.
945  * @note This method is thread safe, but the return value may not be
946  * valid if another thread has pushed to or popped from the queue
947  * before the value returned by the method is acted on. It is
948  * provided as a utility, but may not be meaningful, depending on the
949  * intended usage.
950  *
951  * Since 2.0.8
952  */
953  size_type size() const {
954  Thread::Mutex::Lock lock{mutex};
955  return q.size();
956  }
957 
958 /**
959  * Swaps the contents of 'this' and 'other'. It will not throw
960  * assuming that the swap method of the container type does not throw
961  * (which the C++11 standard requires not to happen with the standard
962  * sequence containers). It is thread safe and the swap is
963  * thread-wise atomic. A non-class function
964  * Cgu::swap(Cgu::AsyncQueue&, Cgu::AsyncQueue&) method is also
965  * provided which will call this method.
966  * @param other The object to be swapped with this one.
967  * @note An object swapped does not, by virtue of the swap, inherit
968  * any threads waiting on the other one. However if threads were
969  * waiting on a swapped object prior to the swap, and it acquires
970  * items by virtue of the swap, the waiting threads will unblock and
971  * extract those items.
972  *
973  * Since 2.0.8
974  */
975  void swap(AsyncQueueDispatch& other) {
976  if (this != &other) {
977  lock2(mutex, other.mutex); // doesn't throw
979  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
980  q.swap(other.q);
981  if (!q.empty()) cond.broadcast();
982  if (!other.q.empty()) other.cond.broadcast();
983  }
984  }
985 
986 /**
987  * The copy assignment operator is strongly exception safe with the
988  * standard sequence containers (it uses copy and swap). It is also
989  * thread safe, as it safely locks both the assignor's and assignee's
990  * mutex to provide a thread-wise atomic assignment.
991  * @param rhs The assignor.
992  * @return The AsyncQueueDispatch object after assignment.
993  * @exception std::bad_alloc The copy constructor of the queue's
994  * container type, and so this assignment operator, might throw
995  * std::bad_alloc if memory is exhausted and the system throws in that
996  * case. This assignment operator will also throw if the copy
997  * constructor of the queue's container type throws any other
998  * exceptions, including if any copy or move constructor or copy or
999  * move assignment operator of a contained item throws.
1000  * @exception Thread::MutexError This assignment operator might
1001  * throw Thread::MutexError if initialization of a transitional
1002  * object's contained mutex fails. (It is often not worth checking
1003  * for this, as it means either memory is exhausted or pthread has run
1004  * out of other resources to create new mutexes.)
1005  * @exception Thread::CondError This assignment operator might throw
1006  * Thread::CondError if initialisation of a transitional object's
1007  * contained condition variable fails. (It is often not worth
1008  * checking for this, as it means either memory is exhausted or
1009  * pthread has run out of other resources to create new condition
1010  * variables.)
1011  * @note The assignee does not, by virtue of the assignment, inherit
1012  * any threads waiting on the assignor. However, if prior to the
1013  * assignment threads were waiting on the assignee and the assignee
1014  * acquires items from the assignor as a result of the assignment, the
1015  * waiting threads will unblock and extract those items.
1016  *
1017  * Since 2.0.8
1018  */
1020  if (this != &rhs) {
1021  lock2(mutex, rhs.mutex); // doesn't throw
1023  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1024  std::queue<T, Container> temp{rhs.q};
1025  q.swap(temp);
1026  if (!q.empty()) cond.broadcast();
1027  }
1028  return *this;
1029  }
1030 
1031 /**
1032  * This move assignment operator is thread safe as regards the
1033  * assignee (the object moved to), but no synchronization is carried
1034  * out with respect to the rvalue assignor/movant. This is because
1035  * temporaries are only visible and accessible in the thread carrying
1036  * out the move operation and synchronization for them would represent
1037  * pointless overhead. In a case where the user uses std::move to
1038  * force a move from a named object, and that named object's lifetime
1039  * is managed by (or the object is otherwise accessed by) a different
1040  * thread than the one making the move, the user must carry out her
1041  * own synchronization with respect to that different thread, both to
1042  * ensure that a consistent view of the the named object is obtained
1043  * and because that object will be mutated by the move. This method
1044  * invokes std::queue's move assignment operator, and therefore has
1045  * the same exception safety as the standard library's implementation
1046  * of that operator. It will not normally throw unless a custom
1047  * allocator is used which throws on move assignment, or the
1048  * destructor of a contained item throws.
1049  * @param rhs The assignor/movant.
1050  * @return The AsyncQueueDispatch object after move assignment.
1051  * @note The assignee does not, by virtue of the move, inherit any
1052  * threads waiting on the assignor/movant. However, if prior to the
1053  * move threads were waiting on the assignee and the assignee acquires
1054  * items from the assignor/movant as a result of the move, from
1055  * version 2.0.9 the waiting threads will unblock and extract those
1056  * items (such unblocking on move assignment did not happen with
1057  * version 2.0.8, which was a bug).
1058  *
1059  * Since 2.0.8
1060  */
1062  Thread::Mutex::Lock lock{mutex};
1063  q = std::move(rhs.q);
1064  if (!q.empty()) cond.broadcast();
1065  return *this;
1066  }
1067 
1068 /**
1069  * @exception std::bad_alloc The default constructor might throw this
1070  * exception if memory is exhausted and the system throws in that
1071  * case.
1072  * @exception Thread::MutexError The default constructor might throw
1073  * this exception if initialisation of the contained mutex fails. (It
1074  * is often not worth checking for this, as it means either memory is
1075  * exhausted or pthread has run out of other resources to create new
1076  * mutexes.)
1077  * @exception Thread::CondError The default constructor might throw
1078  * this exception if initialisation of the contained condition
1079  * variable fails. (It is often not worth checking for this, as it
1080  * means either memory is exhausted or pthread has run out of other
1081  * resources to create new condition variables.)
1082  */
1083  AsyncQueueDispatch() = default;
1084 
1085 /**
1086  * As regards thread safety, the move constructor does not synchronize
1087  * with respect to the initializing rvalue. This is because
1088  * temporaries are only visible and accessible in the thread carrying
1089  * out the move operation and synchronization for them would represent
1090  * pointless overhead. In a case where a user uses std::move to force
1091  * a move from a named object, and that named object's lifetime is
1092  * managed by (or the object is otherwise accessed by) a different
1093  * thread than the one making the move, the user must carry out her
1094  * own synchronization with respect to that different thread, both to
1095  * ensure that a consistent view of the the named object is obtained
1096  * and because that object will be mutated by the move.
1097  * @param rhs The AsyncQueueDispatch object to be moved.
1098  * @exception Thread::MutexError The move constructor might throw
1099  * Thread::MutexError if initialization of the contained mutex fails.
1100  * If it does so this move constructor is strongly exception safe (if
1101  * it is thrown, the object passed as an argument will be unchanged).
1102  * (It is often not worth checking for this, as it means either memory
1103  * is exhausted or pthread has run out of other resources to create
1104  * new mutexes.)
1105  * @exception Thread::CondError The move constructor might throw
1106  * Thread::CondError exception if initialisation of the contained
1107  * condition variable fails. If it does so this move constructor is
1108  * strongly exception safe (if it is thrown, the object passed as an
1109  * argument will be unchanged). (It is often not worth checking for
1110  * this, as it means either memory is exhausted or pthread has run out
1111  * of other resources to create new condition variables.)
1112  * @note The move constructor might also throw if the queue's
1113  * container type's move constructor might throw, but it should not do
1114  * that unless a custom allocator is in use.
1115  *
1116  * Since 2.0.8
1117  */
1118  AsyncQueueDispatch(AsyncQueueDispatch&& rhs): q(std::move(rhs.q)) {}
1119 
1120 /**
1121  * The copy constructor is thread safe, as it locks the initializing
1122  * object's mutex to obtain a consistent view of it.
1123  * @param rhs The AsyncQueueDispatch object to be copied.
1124  * @exception std::bad_alloc The copy constructor of the queue's
1125  * container type, and so this constructor, might throw std::bad_alloc
1126  * if memory is exhausted and the system throws in that case. It will
1127  * also throw if the copy constructor of the queue's container type
1128  * throws any other exceptions, including if any copy or move
1129  * constructor or copy or move assignment operator of a contained item
1130  * throws.
1131  * @exception Thread::MutexError The copy constructor might throw
1132  * Thread::MutexError if initialization of the contained mutex fails.
1133  * (It is often not worth checking for this, as it means either memory
1134  * is exhausted or pthread has run out of other resources to create
1135  * new mutexes.)
1136  * @exception Thread::CondError The copy constructor might throw this
1137  * exception if initialisation of the contained condition variable
1138  * fails. (It is often not worth checking for this, as it means
1139  * either memory is exhausted or pthread has run out of other
1140  * resources to create new condition variables.)
1141  *
1142  * Since 2.0.8
1143  */
1144  // we use the comma operator here to lock the mutex and call the
1145  // copy constructor: the lock will be retained until the end of the
1146  // full expression in which it is lexically situated, namely until
1147  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
1149  q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1150 
1151 /**
1152  * The destructor does not throw unless the destructor of a contained
1153  * item throws. It is thread safe (any thread may delete the
1154  * AsyncQueueDispatch object). Destroying an AsyncQueueDispatch
1155  * object on which another thread is currently blocked results in
1156  * undefined behavior.
1157  */
1159  // lock and unlock the mutex in the destructor so that we have an
1160  // acquire operation to ensure that when the std::queue object is
1161  // destroyed memory is synchronised, so any thread may destroy the
1162  // AsyncQueueDispatch object
1163  Thread::Mutex::Lock lock{mutex};
1164  }
1165 
1166 /* Only has effect if --with-glib-memory-slices-compat or
1167  * --with-glib-memory-slices-no-compat option picked */
1169 };
1170 
1171 /**
1172  * Swaps the contents of two AsyncQueue objects. It will not throw
1173  * assuming that the swap method of the container type does not throw
1174  * (which the C++11 standard requires not to happen with the standard
1175  * sequence containers). It is thread safe and the swap is
1176  * thread-wise atomic.
1177  * @param q1 An object to be swapped with the other.
1178  * @param q2 An object to be swapped with the other.
1179  * @note Calling std::swap on AsyncQueue objects is thread safe but
1180  * does not provide a thread-wise atomic swap (the swapped objects may
1181  * not be mirror images if during the execution of std::swap's default
1182  * algorithm one of them has been modified), although in many cases
1183  * that doesn't matter. If swap() is called without a namespace
1184  * qualifier, argument dependent look-up will pick this one correctly.
1185  *
1186  * Since 2.0.8
1187  */
1188 template <class T, class Container>
1191  q1.swap(q2);
1192 }
1193 
1194 /**
1195  * Swaps the contents of two AsyncQueueDispatch objects. It will not
1196  * throw assuming that the swap method of the container type does not
1197  * throw (which the C++11 standard requires not to happen with the
1198  * standard sequence containers). It is thread safe and the swap is
1199  * thread-wise atomic.
1200  * @param q1 An object to be swapped with the other.
1201  * @param q2 An object to be swapped with the other.
1202  * @note 1. An object swapped does not, by virtue of the swap, inherit
1203  * any threads waiting on the other one. However if threads were
1204  * waiting on a swapped object prior to the swap, and it acquires
1205  * items by virtue of the swap, the waiting threads will unblock and
1206  * extract those items.
1207  * @note 2. Calling std::swap on AsyncQueueDispatch objects is thread
1208  * safe but does not provide a thread-wise atomic swap (the swapped
1209  * objects may not be mirror images if during the execution of
1210  * std::swap's default algorithm one of them has been modified),
1211  * although in many cases that doesn't matter. If swap() is called
1212  * without a namespace qualifier, argument dependent look-up will pick
1213  * this one correctly.
1214  *
1215  * Since 2.0.8
1216  */
1217 template <class T, class Container>
1220  q1.swap(q2);
1221 }
1222 
1223 #if defined(CGU_USE_INHERITABLE_QUEUE) && !defined(DOXYGEN_PARSING)
1224 
1225 /* This is a specialization of AsyncQueue for std::list objects, which
1226  uses std::list::splice() to push or emplace a new item on the
1227  queue. This means that allocation for the push or emplacement
1228  occurs outside the mutex, so reducing contention (a tip from a talk
1229  by Sean Parent of Adobe). This is first available in version
1230  2.0.20/2.2.3.
1231  */
1232 template <class T, class Allocator>
1233 class AsyncQueue<T, std::list<T, Allocator> > {
1234 public:
1235  typedef std::list<T, Allocator> Container;
1236  typedef typename Container::value_type value_type;
1237  typedef typename Container::size_type size_type;
1238  typedef Container container_type;
1239 private:
1240  mutable Thread::Mutex mutex;
1241  // 23.6.3.1 of C++11 requires std::queue to have a protected
1242  // container member called 'c' for the purposes of derivation. This
1243  // specialisation will have the same binary layout as the
1244  // unspecialized version on any practical implementation: all we do
1245  // is add a splice_end() member
1246  class Q: public std::queue<T, Container> {
1247  public:
1248  void splice_end(Container&& lst) {
1249  this->c.splice(this->c.end(), std::move(lst));
1250  }
1251  } q;
1252 
1253  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1254  m1.lock();
1255  for(;;) {
1256  if (!m2.trylock()) {
1257  return;
1258  }
1259  m1.unlock();
1260  // spin nicely
1261 #ifdef CGU_USE_SCHED_YIELD
1262  sched_yield();
1263 #else
1264  usleep(10);
1265 #endif
1266  m1.lock();
1267  }
1268  }
1269 public:
1270  void push(const value_type& obj) {
1271  Container temp{obj};
1272  Thread::Mutex::Lock lock{mutex};
1273  // splice_end doesn't throw
1274  q.splice_end(std::move(temp));
1275  }
1276 
1277  void push(value_type&& obj) {
1278  Container temp{std::move(obj)};
1279  Thread::Mutex::Lock lock{mutex};
1280  // splice_end doesn't throw
1281  q.splice_end(std::move(temp));
1282  }
1283 
1284  template<class... Args>
1285  void emplace(Args&&... args) {
1286  Container temp;
1287  temp.emplace_back(std::forward<Args>(args)...);
1288  Thread::Mutex::Lock lock{mutex};
1289  // splice_end doesn't throw
1290  q.splice_end(std::move(temp));
1291  }
1292 
1293  void pop(value_type& obj) {
1294  Thread::Mutex::Lock lock{mutex};
1295  if (q.empty()) throw AsyncQueuePopError();
1296  obj = q.front();
1297  q.pop();
1298  }
1299 
1300  void move_pop(value_type& obj) {
1301  Thread::Mutex::Lock lock{mutex};
1302  if (q.empty()) throw AsyncQueuePopError();
1303  obj = std::move(q.front());
1304  q.pop();
1305  }
1306 
1307  void pop() {
1308  Thread::Mutex::Lock lock{mutex};
1309  if (q.empty()) throw AsyncQueuePopError();
1310  q.pop();
1311  }
1312 
1313  bool empty() const {
1314  Thread::Mutex::Lock lock{mutex};
1315  return q.empty();
1316  }
1317 
1318  size_type size() const {
1319  Thread::Mutex::Lock lock{mutex};
1320  return q.size();
1321  }
1322 
1323  void swap(AsyncQueue& other) {
1324  if (this != &other) {
1325  lock2(mutex, other.mutex); // doesn't throw
1326  Thread::Mutex::Lock l1{mutex, Thread::locked};
1327  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
1328  q.swap(other.q);
1329  }
1330  }
1331 
1332  AsyncQueue& operator=(const AsyncQueue& rhs) {
1333  if (this != &rhs) {
1334  lock2(mutex, rhs.mutex); // doesn't throw
1335  Thread::Mutex::Lock l1{mutex, Thread::locked};
1336  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1337  Q temp{rhs.q};
1338  q.swap(temp);
1339  }
1340  return *this;
1341  }
1342 
1343  AsyncQueue& operator=(AsyncQueue&& rhs) {
1344  Thread::Mutex::Lock lock{mutex};
1345  q = std::move(rhs.q);
1346  return *this;
1347  }
1348 
1349  AsyncQueue() = default;
1350 
1351  AsyncQueue(AsyncQueue&& rhs): q(std::move(rhs.q)) {}
1352 
1353  AsyncQueue(const AsyncQueue& rhs): q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1354 
1355  ~AsyncQueue() {
1356  Thread::Mutex::Lock lock{mutex};
1357  }
1358 
1360 };
1361 
1362 /* This is a specialization of AsyncQueueDispatch for std::list
1363  objects, which uses std::list::splice() to push or emplace a new
1364  item on the queue. This means that allocation for the push or
1365  emplacement occurs outside the mutex, so reducing contention (a tip
1366  from a talk by Sean Parent of Adobe). This is first available in
1367  version 2.0.20/2.2.3.
1368  */
1369 template <class T, class Allocator>
1370 class AsyncQueueDispatch<T, std::list<T, Allocator> > {
1371 public:
1372  typedef std::list<T, Allocator> Container;
1373  typedef typename Container::value_type value_type;
1374  typedef typename Container::size_type size_type;
1375  typedef Container container_type;
1376 private:
1377  mutable Thread::Mutex mutex;
1378  Thread::Cond cond;
1379  // 23.6.3.1 of C++11 requires std::queue to have a protected
1380  // container member called 'c' for the purposes of derivation. This
1381  // specialisation will have the same binary layout as the
1382  // unspecialized version on any practical implementation: all we do
1383  // is add a splice_end() member
1384  class Q: public std::queue<T, Container> {
1385  public:
1386  void splice_end(Container&& lst) {
1387  this->c.splice(this->c.end(), std::move(lst));
1388  }
1389  } q;
1390 
1391  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1392  m1.lock();
1393  for(;;) {
1394  if (!m2.trylock()) {
1395  return;
1396  }
1397  m1.unlock();
1398  // spin nicely
1399 #ifdef CGU_USE_SCHED_YIELD
1400  sched_yield();
1401 #else
1402  usleep(10);
1403 #endif
1404  m1.lock();
1405  }
1406  }
1407 public:
1408  void push(const value_type& obj) {
1409  Container temp{obj};
1410  Thread::Mutex::Lock lock{mutex};
1411  // splice_end doesn't throw
1412  q.splice_end(std::move(temp));
1413  cond.signal();
1414  }
1415 
1416  void push(value_type&& obj) {
1417  Container temp{std::move(obj)};
1418  Thread::Mutex::Lock lock{mutex};
1419  // splice_end doesn't throw
1420  q.splice_end(std::move(temp));
1421  cond.signal();
1422  }
1423 
1424  template<class... Args>
1425  void emplace(Args&&... args) {
1426  Container temp;
1427  temp.emplace_back(std::forward<Args>(args)...);
1428  Thread::Mutex::Lock lock{mutex};
1429  // splice_end doesn't throw
1430  q.splice_end(std::move(temp));
1431  cond.signal();
1432  }
1433 
1434  void pop(value_type& obj) {
1435  Thread::Mutex::Lock lock{mutex};
1436  if (q.empty()) throw AsyncQueuePopError();
1437  obj = q.front();
1438  q.pop();
1439  }
1440 
1441  void move_pop(value_type& obj) {
1442  Thread::Mutex::Lock lock{mutex};
1443  if (q.empty()) throw AsyncQueuePopError();
1444  obj = std::move(q.front());
1445  q.pop();
1446  }
1447 
1448  void pop_dispatch(value_type& obj) {
1449  Thread::Mutex::Lock lock{mutex};
1450  while (q.empty()) cond.wait(mutex);
1451  Thread::CancelBlock b;
1452  obj = q.front();
1453  q.pop();
1454  }
1455 
1456  void move_pop_dispatch(value_type& obj) {
1457  Thread::Mutex::Lock lock{mutex};
1458  while (q.empty()) cond.wait(mutex);
1459  Thread::CancelBlock b;
1460  obj = std::move(q.front());
1461  q.pop();
1462  }
1463 
1464  bool pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1465  timespec ts;
1466  Thread::Cond::get_abs_time(ts, millisec);
1467  Thread::Mutex::Lock lock{mutex};
1468  while (q.empty()) {
1469  if (cond.timed_wait(mutex, ts)) return true;
1470  }
1471  Thread::CancelBlock b;
1472  obj = q.front();
1473  q.pop();
1474  return false;
1475  }
1476 
1477  bool move_pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1478  timespec ts;
1479  Thread::Cond::get_abs_time(ts, millisec);
1480  Thread::Mutex::Lock lock{mutex};
1481  while (q.empty()) {
1482  if (cond.timed_wait(mutex, ts)) return true;
1483  }
1484  Thread::CancelBlock b;
1485  obj = std::move(q.front());
1486  q.pop();
1487  return false;
1488  }
1489 
1490  void pop() {
1491  Thread::Mutex::Lock lock{mutex};
1492  if (q.empty()) throw AsyncQueuePopError();
1493  q.pop();
1494  }
1495 
1496  bool empty() const {
1497  Thread::Mutex::Lock lock{mutex};
1498  return q.empty();
1499  }
1500 
1501  size_type size() const {
1502  Thread::Mutex::Lock lock{mutex};
1503  return q.size();
1504  }
1505 
1506  void swap(AsyncQueueDispatch& other) {
1507  if (this != &other) {
1508  lock2(mutex, other.mutex); // doesn't throw
1509  Thread::Mutex::Lock l1{mutex, Thread::locked};
1510  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
1511  q.swap(other.q);
1512  if (!q.empty()) cond.broadcast();
1513  if (!other.q.empty()) other.cond.broadcast();
1514  }
1515  }
1516 
1518  if (this != &rhs) {
1519  lock2(mutex, rhs.mutex); // doesn't throw
1520  Thread::Mutex::Lock l1{mutex, Thread::locked};
1521  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1522  Q temp{rhs.q};
1523  q.swap(temp);
1524  if (!q.empty()) cond.broadcast();
1525  }
1526  return *this;
1527  }
1528 
1530  Thread::Mutex::Lock lock{mutex};
1531  q = std::move(rhs.q);
1532  if (!q.empty()) cond.broadcast();
1533  return *this;
1534  }
1535 
1536  AsyncQueueDispatch() = default;
1537 
1538  AsyncQueueDispatch(AsyncQueueDispatch&& rhs): q(std::move(rhs.q)) {}
1539 
1541  q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1542 
1544  Thread::Mutex::Lock lock{mutex};
1545  }
1546 
1548 };
1549 
1550 #endif // CGU_USE_INHERITABLE_QUEUE
1551 
1552 } // namespace Cgu
1553 
1554 #endif