c++-gtk-utils
async_queue.h
Go to the documentation of this file.
1 /* Copyright (C) 2006 to 2014 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 <pthread.h>
82 
83 #include <c++-gtk-utils/mutex.h>
84 #include <c++-gtk-utils/thread.h>
86 
87 #ifdef CGU_USE_SCHED_YIELD
88 #include <sched.h>
89 #else
90 #include <unistd.h>
91 #endif
92 
93 namespace Cgu {
94 
95 /**
96  * @class AsyncQueuePopError async_queue.h c++-gtk-utils/async_queue.h
97  * @brief An exception thrown if calling pop() on a AsyncQueue or
98  * AsyncQueueDispatch object fails because the queue is empty.
99  * @sa AsyncQueue AsyncQueueDispatch
100  */
101 
102 struct AsyncQueuePopError: public std::exception {
103  virtual const char* what() const throw() {return "AsyncQueuePopError: popping from empty AsyncQueue object\n";}
104 };
105 
106 
107 /**
108  * @class AsyncQueue async_queue.h c++-gtk-utils/async_queue.h
109  * @brief A thread-safe asynchronous queue.
110  * @sa AsyncQueueDispatch AsyncResult
111  *
112  * AsyncQueue is a class which provides some of the functionality of a
113  * std::queue object (but note that the AsyncQueue::pop(value_type&
114  * obj) and AsyncQueue::move_pop(value_type& obj) methods provide the
115  * popped element by reference - see the comments on that method for
116  * the reason), except that it has mutex locking of the data container
117  * so as to permit pushing and popping from different threads. It is
118  * therefore useful for passing data between threads, perhaps in
119  * response to a signal being emitted from a Notifier object. Data
120  * can be pushed or pulled by move constructor/move assignment
121  * operator or by means of a std::unique_ptr object, SharedLockPtr
122  * object or an IntrusivePtr object referencing data derived from
123  * IntrusiveLockCounter.
124  *
125  * By default the queue uses a std::list object as its container
126  * because when adding an item to the queue all allocation can take
127  * place outside the queue object's mutex. However, for types which
128  * have low overhead copy or move constructors, this can be changed
129  * to, say, a std::deque object by specifying it as the second
130  * template parameter.
131  *
132  * If the library is installed using the
133  * \--with-glib-memory-slices-compat or
134  * \--with-glib-memory-slices-no-compat configuration options, any
135  * AsyncQueue objects constructed on free store will be constructed in
136  * glib memory slices. This does not affect the queue container
137  * itself: to change the allocator of the C++ container, a custom
138  * allocator type can be provided when the AsyncQueue object is
139  * instantiated offering the standard allocator interface. If glib
140  * memory slices are not used or no AsyncQueue objects are constructed
141  * on free store, it is not necessary to call g_thread_init() before
142  * manipulating or using an AsyncQueue object in multiple threads, but
143  * prior to glib version 2.32 glib itself (and thus glib memory
144  * slices) are not thread safe unless that function has been called.
145  */
146 
147 template <class T, class Container = std::list<T> > class AsyncQueue {
148 public:
149  typedef typename Container::value_type value_type;
150  typedef typename Container::size_type size_type;
151  typedef Container container_type;
152 private:
153 // TODO: put 'q' after 'mutex' at the next ABI break, so move
154 // construction is strongly exception safe
155  std::queue<T, Container> q;
156  mutable Thread::Mutex mutex;
157 
158 // TODO: at the next ABI break make this method explicitly static
159 // this method won't throw: it is for the user to ensure the arguments
160 // do not refer to the same mutex object
161  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
162  m1.lock();
163  for(;;) {
164  if (!m2.trylock()) {
165  return;
166  }
167  m1.unlock();
168  // spin nicely
169 #ifdef CGU_USE_SCHED_YIELD
170  sched_yield();
171 #else
172  usleep(10);
173 #endif
174  m1.lock();
175  }
176  }
177 public:
178 /**
179  * Pushes an item onto the queue. This method has strong exception
180  * safety if the container is a std::list or std::deque container (the
181  * default is std::list), except that if std::deque is used as the
182  * container and the copy constructor, move constructor, copy
183  * assignment operator or move assignment operator of the queue item
184  * throws, it only gives the basic exception guarantee (and the basic
185  * guarantee is not given by std::deque if the queue item's move
186  * constructor throws and it uses a non-default allocator which does
187  * not provide for it to be CopyInsertable). It is thread safe.
188  * @param obj The item to be pushed onto the queue.
189  * @exception std::bad_alloc The method might throw std::bad_alloc if
190  * memory is exhausted and the system throws in that case. It might
191  * also throw if the copy constructor, move constructor, assignment
192  * operator or move assignment operator of the queue item might throw.
193  */
194  void push(const value_type& obj) {
195  Thread::Mutex::Lock lock{mutex};
196  q.push(obj);
197  }
198 
199 /**
200  * Pushes an item onto the queue. This method has strong exception
201  * safety if the container is a std::list or std::deque container (the
202  * default is std::list), except that if std::deque is used as the
203  * container and the copy constructor, move constructor, copy
204  * assignment operator or move assignment operator of the queue item
205  * throws, it only gives the basic exception guarantee (and the basic
206  * guarantee is not given by std::deque if the queue item's move
207  * constructor throws and it uses a non-default allocator which does
208  * not provide for it to be CopyInsertable). It is thread safe.
209  * @param obj The item to be pushed onto the queue.
210  * @exception std::bad_alloc The method might throw std::bad_alloc if
211  * memory is exhausted and the system throws in that case. It might
212  * also throw if the copy constructor, move constructor, assignment
213  * operator or move assignment operator of the queue item might throw.
214  *
215  * Since 2.0.0-rc5
216  */
217  void push(value_type&& obj) {
218  Thread::Mutex::Lock lock{mutex};
219  q.push(std::move(obj));
220  }
221 
222 /**
223  * Pushes an item onto the queue by constructing it in place: that is,
224  * by passing to this method the item's constructor's arguments,
225  * rather than the item itself. This method has strong exception
226  * safety if the container is a std::list or std::deque container (the
227  * default is std::list). (Technically, for a std::deque container,
228  * emplace() only offers the same exception guarantees as does push(),
229  * namely only the basic guarantee where a copy or move of the queue
230  * item throws during the call, but the purpose of emplace is to
231  * construct in place and any reasonable implementation will not copy
232  * or move the queue item.) It is thread safe.
233  * @param args The constructor arguments for the item to be pushed
234  * onto the queue.
235  * @exception std::bad_alloc The method might throw std::bad_alloc if
236  * memory is exhausted and the system throws in that case. It might
237  * also throw if the item's constructor (including any of its
238  * constructor arguments) might throw when constructing the item.
239  * @note The constructor of the item pushed onto the queue must not
240  * access any of the methods of the same queue object, or a deadlock
241  * might occur.
242  *
243  * Since 2.0.0-rc5
244  */
245  template<class... Args>
246  void emplace(Args&&... args) {
247  Thread::Mutex::Lock lock{mutex};
248  q.emplace(std::forward<Args>(args)...);
249  }
250 
251 /**
252  * Pops an item from the queue. This method has strong exception
253  * safety if the container is a std::deque or std::list container (the
254  * default is std::list), provided the destructor of a contained item
255  * does not throw. It is thread safe.
256  * @param obj A value type reference to which the item at the front of
257  * the queue will be assigned.
258  * @exception AsyncQueuePopError If the queue is empty when a pop is
259  * attempted, this method will throw AsyncQueuePopError. It might
260  * also throw if the copy assignment operator of the queue item might
261  * throw. In order to complete pop operations atomically under a
262  * single lock and to retain strong exception safety, the object into
263  * which the popped data is to be placed is passed as an argument by
264  * reference (this avoids a copy from a temporary object after the
265  * data has been extracted from the queue, which would occur if the
266  * item extracted were returned by value). It might also throw if the
267  * destructor of the queue item might throw (but that should never
268  * happen), or if the empty() method of the container type throws
269  * (which would not happen on any sane implementation).
270  */
271  void pop(value_type& obj) {
272  Thread::Mutex::Lock lock{mutex};
273  if (q.empty()) throw AsyncQueuePopError();
274  obj = q.front();
275  q.pop();
276  }
277 
278 /**
279  * Pops an item from the queue using the contained type's move
280  * assignment operator, if it has one. This method is identical to
281  * the pop() method if that type has no move assignment operator.
282  * This method has strong exception safety if the container is a
283  * std::deque or std::list container (the default is std::list),
284  * provided the destructor of a contained item does not throw and the
285  * move assignment operator of a contained item has strong exception
286  * safety. It is thread safe. Use this method in preference to the
287  * pop() method if it is known that the contained items' move
288  * assignment operator does not throw or is strongly exception safe,
289  * or if the use case does not require strong exception safety. This
290  * method (or the move_pop_basic() method) must be used in place of
291  * the pop() method if the contained type has a move assignment
292  * operator but no copy assignment operator (such as a std::unique_ptr
293  * object).
294  * @param obj A value type reference to which the item at the front of
295  * the queue will be move assigned.
296  * @exception AsyncQueuePopError If the queue is empty when a pop is
297  * attempted, this method will throw AsyncQueuePopError. It might
298  * also throw if the move assignment operator of the queue item might
299  * throw, or if it has no move assignment operator and its copy
300  * assignment operator throws. In order to complete pop operations
301  * atomically under a single lock and to retain strong exception
302  * safety, the object into which the popped data is to be placed is
303  * passed as an argument by reference (this avoids a move from a
304  * temporary object after the data has been extracted from the queue,
305  * which would occur if the item extracted were returned by value).
306  * It might also throw if the destructor of the queue item might throw
307  * (but that should never happen), or if the empty() method of the
308  * container type throws (which would not happen on any sane
309  * implementation).
310  *
311  * Since 2.0.11
312  */
313  void move_pop(value_type& obj) {
314  Thread::Mutex::Lock lock{mutex};
315  if (q.empty()) throw AsyncQueuePopError();
316  obj = std::move(q.front());
317  q.pop();
318  }
319 
320 /**
321  * Pops an item from the queue using the contained type's move
322  * assignment operator, if it has one, or if not using its copy
323  * assignment operator. This method is only available where the
324  * queue's container is a std::list object (which is the default), and
325  * does the same as the move_pop() method except that when popping the
326  * only thing which is done to the queue's container's internal state
327  * within the queue object's mutex is to swap some pointers: in
328  * particular, deallocation of the list node at the front of the queue
329  * occurs outside that mutex, as does assignment to this method's
330  * argument. Given that, if the queue's container is a list, any new
331  * node is also constructed outside the mutex when pushing or
332  * emplacing an item onto the queue, this minimizes contention between
333  * threads: it gets as close to lock-free performance as it is
334  * possible to get with the standard containers.
335  *
336  * However this minimizing of contention comes at a cost, which is
337  * that if the contained item's move assignment operator (or if it has
338  * none, its copy assignment operator) throws, then only the basic
339  * exception guarantee is offered (hence the name of this method).
340  * This means that although the AsyncQueue object would be left in a
341  * valid state in the event of such throwing, the item at the front of
342  * the queue would be lost. As in the case of the pop() and
343  * move_pop() methods, in addition only the basic exception guarantee
344  * is offered if the destructor of the contained item throws. Only
345  * use this method if the queue's container is a std::list object, and
346  * if either it is known that the contained item's move assignment
347  * operator (or if it has none, its copy assignment operator) does not
348  * throw, or the use case does not require strong exception safety.
349  * This method is thread safe.
350  *
351  * If this method is called for an AsyncQueue object whose container
352  * is not a std::list object, it will hand off to the move_pop()
353  * method, which is separately documented.
354  * @param obj A value type reference to which the item at the front of
355  * the queue will be move assigned.
356  * @exception AsyncQueuePopError If the queue is empty when a pop is
357  * attempted, this method will throw AsyncQueuePopError. It might
358  * also throw if the move assignment operator of the queue item might
359  * throw or it has no move assignment operator and its copy assignment
360  * operator throws (in which case only the basic exception guarantee
361  * is offered). It might also throw if the destructor of the queue
362  * item might throw (but that should never happen), if the empty()
363  * method of the container type throws (which would not happen on any
364  * sane implementation) or if the constructor of the implementation's
365  * list allocator throws (which would be highly unusual). In the
366  * event of any of the last two throwing, the strong exception
367  * guarantee is offered.
368  *
369  * Since 2.0.26
370  */
371 // See the specialisation for lists for the implementation of this
372 // method. For queues which do not use a list as their container,
373 // this hands off to move_pop().
374  void move_pop_basic(value_type& obj) {
375  move_pop(obj);
376  }
377 
378 /**
379  * Discards the item at the front of the queue. This method has
380  * strong exception safety if the container is a std::deque or
381  * std::list container (the default is std::list), provided the
382  * destructor of a contained item does not throw. It is thread safe.
383  * @exception AsyncQueuePopError If the queue is empty when a pop is
384  * attempted, this method will throw AsyncQueuePopError. It might
385  * also throw if the destructor of the queue item might throw (but
386  * that should never happen), or if the empty() method of the
387  * container type throws (which would not happen on any sane
388  * implementation).
389  */
390  void pop() {
391  Thread::Mutex::Lock lock{mutex};
392  if (q.empty()) throw AsyncQueuePopError();
393  q.pop();
394  }
395 
396 /**
397  * @return Whether the queue is empty. It will not throw assuming
398  * that the empty() method of the container type does not throw, as it
399  * will not on any sane implementation.
400  * @note This method is thread safe, but the return value may not be
401  * valid if another thread has pushed to or popped from the queue
402  * before the value returned by the method is acted on. It is
403  * provided as a utility, but may not be meaningful, depending on the
404  * intended usage.
405  */
406  bool empty() const {
407  Thread::Mutex::Lock lock{mutex};
408  return q.empty();
409  }
410 
411 /**
412  * @return The number of items currently in the queue. It will not
413  * throw assuming that the size() method of the container type does
414  * not throw, as it will not on any sane implementation.
415  * @note This method is thread safe, but the return value may not be
416  * valid if another thread has pushed to or popped from the queue
417  * before the value returned by the method is acted on. It is
418  * provided as a utility, but may not be meaningful, depending on the
419  * intended usage.
420  *
421  * Since 2.0.8
422  */
423  size_type size() const {
424  Thread::Mutex::Lock lock{mutex};
425  return q.size();
426  }
427 
428 /**
429  * Swaps the contents of 'this' and 'other'. It will not throw
430  * assuming that the swap method of the container type does not throw
431  * (which the C++11/14 standard requires not to happen with the
432  * standard sequence containers). It is thread safe and the swap is
433  * thread-wise atomic. A non-class function
434  * Cgu::swap(Cgu::AsyncQueue&, Cgu::AsyncQueue&) method is also
435  * provided which will call this method.
436  * @param other The object to be swapped with this one.
437  *
438  * Since 2.0.8
439  */
440  void swap(AsyncQueue& other) {
441  if (this != &other) {
442  lock2(mutex, other.mutex); // doesn't throw
444  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
445  q.swap(other.q);
446  }
447  }
448 
449 /**
450  * The copy assignment operator is strongly exception safe with the
451  * standard sequence containers (it uses copy and swap). It is also
452  * thread safe, as it safely locks both the assignor's and assignee's
453  * mutex to provide a thread-wise atomic assignment.
454  * @param rhs The assignor.
455  * @return The AsyncQueue object after assignment.
456  * @exception std::bad_alloc The copy constructor of the queue's
457  * container type, and so this assignment operator, might throw
458  * std::bad_alloc if memory is exhausted and the system throws in that
459  * case. This assignment operator will also throw if the copy
460  * constructor of the queue's container type throws any other
461  * exceptions, including if any copy or move constructor or copy or
462  * move assignment operator of a contained item throws.
463  * @exception Thread::MutexError This assignment operator might throw
464  * Thread::MutexError if initialization of a transitional object's
465  * contained mutex fails. (It is often not worth checking for this,
466  * as it means either memory is exhausted or pthread has run out of
467  * other resources to create new mutexes.)
468  *
469  * Since 2.0.8
470  */
472  if (this != &rhs) {
473  lock2(mutex, rhs.mutex); // doesn't throw
475  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
476  std::queue<T, Container> temp{rhs.q};
477  q.swap(temp);
478  }
479  return *this;
480  }
481 
482 /**
483  * This move assignment operator is thread safe as regards the
484  * assignee (the object moved to), but no synchronization is carried
485  * out with respect to the rvalue assignor/movant. This is because
486  * temporaries are only visible and accessible in the thread carrying
487  * out the move operation and synchronization for them would represent
488  * pointless overhead. In a case where the user uses std::move to
489  * force a move from a named object, and that named object's lifetime
490  * is managed by (or the object is otherwise accessed by) a different
491  * thread than the one making the move, the user must carry out her
492  * own synchronization with respect to that different thread, both to
493  * ensure that a consistent view of the the named object is obtained
494  * and because that object will be mutated by the move. This method
495  * invokes std::queue's move assignment operator, and therefore has
496  * the same exception safety as the standard library's implementation
497  * of that operator. It will not normally throw unless a custom
498  * allocator is used which throws on move assignment, or the
499  * destructor of a contained item throws.
500  * @param rhs The assignor/movant.
501  * @return The AsyncQueue object after move assignment.
502  *
503  * Since 2.0.8
504  */
506  Thread::Mutex::Lock lock{mutex};
507  q = std::move(rhs.q);
508  return *this;
509  }
510 
511 /**
512  * @exception std::bad_alloc The default constructor might throw
513  * std::bad_alloc if memory is exhausted and the system throws in that
514  * case.
515  * @exception Thread::MutexError The default constructor might throw
516  * Thread::MutexError if initialization of the contained mutex fails.
517  * (It is often not worth checking for this, as it means either memory
518  * is exhausted or pthread has run out of other resources to create
519  * new mutexes.)
520  */
521  AsyncQueue() = default;
522 
523 /**
524  * As regards thread safety, the move constructor does not synchronize
525  * with respect to the initializing rvalue. This is because
526  * temporaries are only visible and accessible in the thread carrying
527  * out the move operation and synchronization for them would represent
528  * pointless overhead. In a case where a user uses std::move to force
529  * a move from a named object, and that named object's lifetime is
530  * managed by (or the object is otherwise accessed by) a different
531  * thread than the one making the move, the user must carry out her
532  * own synchronization with respect to that different thread, both to
533  * ensure that a consistent view of the the named object is obtained
534  * and because that object will be mutated by the move.
535  * @param rhs The AsyncQueue object to be moved.
536  * @exception Thread::MutexError The move constructor might throw
537  * Thread::MutexError if initialization of the contained mutex fails.
538  * (It is often not worth checking for this, as it means either memory
539  * is exhausted or pthread has run out of other resources to create
540  * new mutexes.) It might also throw if the queue's container type's
541  * move constructor might throw, but it should not do that unless a
542  * custom allocator is in use.
543  * @note If this constructor throws Thread::MutexError, and a named
544  * object is moved using std::move, this constructor is not strongly
545  * exception safe (items in the moved queue will be lost). Fixing
546  * this efficiently requires changing the order of construction of
547  * data members of this class, which cannot be done until the next ABI
548  * break for this library as it would alter object layout. As noted
549  * above, in most cases the possibility of Thread::MutexError throwing
550  * can be ignored, but where that is not the case and strong exception
551  * safety is wanted, the user should either not employ std::move with
552  * named objects when invoking this class's constructors, or should
553  * construct an AsyncQueue object using the default constructor and
554  * then move assign to it.
555  *
556  * Since 2.0.8
557  */
558  AsyncQueue(AsyncQueue&& rhs): q(std::move(rhs.q)) {}
559 
560 /**
561  * The copy constructor is thread safe, as it locks the initializing
562  * object's mutex to obtain a consistent view of it.
563  * @param rhs The AsyncQueue object to be copied.
564  * @exception std::bad_alloc The copy constructor of the queue's
565  * container type, and so this constructor, might throw std::bad_alloc
566  * if memory is exhausted and the system throws in that case. It will
567  * also throw if the copy constructor of the queue's container type
568  * throws any other exceptions, including if any copy or move
569  * constructor or copy or move assignment operator of a contained item
570  * throws.
571  * @exception Thread::MutexError The copy constructor might throw
572  * Thread::MutexError if initialization of the contained mutex fails.
573  * (It is often not worth checking for this, as it means either memory
574  * is exhausted or pthread has run out of other resources to create
575  * new mutexes.)
576  *
577  * Since 2.0.8
578  */
579  // we use the comma operator here to lock the mutex and call the
580  // copy constructor: the lock will be retained until the end of the
581  // full expression in which it is lexically situated, namely until
582  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
583  AsyncQueue(const AsyncQueue& rhs): q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
584 
585 /**
586  * The destructor does not throw unless the destructor of a contained
587  * item throws. It is thread safe (any thread may delete the
588  * AsyncQueue object).
589  */
591  // lock and unlock the mutex in the destructor so that we have an
592  // acquire operation to ensure that when the std::queue object is
593  // destroyed memory is synchronised, so any thread may destroy the
594  // AsyncQueue object
595  Thread::Mutex::Lock lock{mutex};
596  }
597 
598 /* Only has effect if --with-glib-memory-slices-compat or
599  * --with-glib-memory-slices-no-compat option picked */
601 };
602 
603 /**
604  * @class AsyncQueueDispatch async_queue.h c++-gtk-utils/async_queue.h
605  * @brief A thread-safe asynchronous queue with a blocking pop()
606  * method.
607  * @sa AsyncQueue AsyncResult
608  *
609  * AsyncQueueDispatch is a class which has blocking pop_dispatch()
610  * and move_pop_dispatch() methods, which allows it to be waited on by a dedicated
611  * event/message dispatching thread for incoming work (represented by
612  * the data pushed onto the queue). In the same way, it can be used
613  * to implement thread pools, by having threads in the pool waiting on
614  * the queue. The AsyncResult class can be useful for passing results
615  * between threads in conjunction with AsyncQueueDispatch (the
616  * documentation on AsyncResult gives an example).
617  *
618  * By default the queue uses a std::list object as its container
619  * because when adding an item to the queue all allocation can take
620  * place outside the queue object's mutex. However, for types which
621  * have low overhead copy or move constructors, this can be changed
622  * to, say, a std::deque object by specifying it as the second
623  * template parameter.
624  *
625  * If the library is installed using the
626  * \--with-glib-memory-slices-compat or
627  * \--with-glib-memory-slices-no-compat configuration options, any
628  * AsyncQueueDispatch objects constructed on free store will be
629  * constructed in glib memory slices. This does not affect the queue
630  * container itself: to change the allocator of the C++ container, a
631  * custom allocator type can be provided when the AsyncQueueDispatch
632  * object is instantiated offering the standard allocator interface.
633  * If glib memory slices are not used or no AsyncQueueDispatch objects
634  * are constructed on free store, it is not necessary to call
635  * g_thread_init() before manipulating or using an AsyncQueueDispatch
636  * object in multiple threads, but prior to glib version 2.32 glib
637  * itself (and thus glib memory slices) are not thread safe unless
638  * that function has been called.
639  */
640 
641 template <class T, class Container = std::list<T> > class AsyncQueueDispatch {
642 public:
643  typedef typename Container::value_type value_type;
644  typedef typename Container::size_type size_type;
645  typedef Container container_type;
646 private:
647 // TODO: put 'q' after 'mutex' and 'cond' at the next ABI break, so
648 // move construction is strongly exception safe
649  std::queue<T, Container> q;
650  mutable Thread::Mutex mutex;
651  Thread::Cond cond;
652 
653 // TODO: at the next ABI break make this method explicitly static
654 // this method won't throw: it is for the user to ensure the arguments
655 // do not refer to the same mutex object
656  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
657  m1.lock();
658  for(;;) {
659  if (!m2.trylock()) {
660  return;
661  }
662  m1.unlock();
663  // spin nicely
664 #ifdef CGU_USE_SCHED_YIELD
665  sched_yield();
666 #else
667  usleep(10);
668 #endif
669  m1.lock();
670  }
671  }
672 public:
673 /**
674  * Pushes an item onto the queue. This method has strong exception
675  * safety if the container is a std::list or std::deque container (the
676  * default is std::list), except that if std::deque is used as the
677  * container and the copy constructor, move constructor, copy
678  * assignment operator or move assignment operator of the queue item
679  * throws, it only gives the basic exception guarantee (and the basic
680  * guarantee is not given by std::deque if the queue item's move
681  * constructor throws and it uses a non-default allocator which does
682  * not provide for it to be CopyInsertable). It is thread safe.
683  * @param obj The item to be pushed onto the queue.
684  * @exception std::bad_alloc The method might throw std::bad_alloc if
685  * memory is exhausted and the system throws in that case. It might
686  * also throw if the copy constructor, move constructor, assignment
687  * operator or move assignment operator of the queue item might throw.
688  */
689  void push(const value_type& obj) {
690  Thread::Mutex::Lock lock{mutex};
691  q.push(obj);
692  cond.signal();
693  }
694 
695 /**
696  * Pushes an item onto the queue. This method has strong exception
697  * safety if the container is a std::list or std::deque container (the
698  * default is std::list), except that if std::deque is used as the
699  * container and the copy constructor, move constructor, copy
700  * assignment operator or move assignment operator of the queue item
701  * throws, it only gives the basic exception guarantee (and the basic
702  * guarantee is not given by std::deque if the queue item's move
703  * constructor throws and it uses a non-default allocator which does
704  * not provide for it to be CopyInsertable). It is thread safe.
705  * @param obj The item to be pushed onto the queue.
706  * @exception std::bad_alloc The method might throw std::bad_alloc if
707  * memory is exhausted and the system throws in that case. It might
708  * also throw if the copy constructor, move constructor, assignment
709  * operator or move assignment operator of the queue item might throw.
710  *
711  * Since 2.0.0-rc5
712  */
713  void push(value_type&& obj) {
714  Thread::Mutex::Lock lock{mutex};
715  q.push(std::move(obj));
716  cond.signal();
717  }
718 
719 /**
720  * Pushes an item onto the queue by constructing it in place: that is,
721  * by passing to this method the item's constructor's arguments,
722  * rather than the item itself. This method has strong exception
723  * safety if the container is a std::list or std::deque container (the
724  * default is std::list). (Technically, for a std::deque container,
725  * emplace() only offers the same exception guarantees as does push(),
726  * namely only the basic guarantee where a copy or move of the queue
727  * item throws during the call, but the purpose of emplace is to
728  * construct in place and any reasonable implementation will not copy
729  * or move the queue item.) It is thread safe.
730  * @param args The constructor arguments for the item to be pushed
731  * onto the queue.
732  * @exception std::bad_alloc The method might throw std::bad_alloc if
733  * memory is exhausted and the system throws in that case. It might
734  * also throw if the item's constructor (including any of its
735  * constructor arguments) might throw when constructing the item.
736  * @note The constructor of the item pushed onto the queue must not
737  * access any of the methods of the same queue object, or a deadlock
738  * might occur.
739  *
740  * Since 2.0.0-rc5
741  */
742  template<class... Args>
743  void emplace(Args&&... args) {
744  Thread::Mutex::Lock lock{mutex};
745  q.emplace(std::forward<Args>(args)...);
746  cond.signal();
747  }
748 
749 /**
750  * Pops an item from the queue. This method has strong exception
751  * safety if the container is a std::deque or std::list container (the
752  * default is std::list), provided the destructor of a contained item
753  * does not throw. It is thread safe.
754  * @param obj A value type reference to which the item at the front of
755  * the queue will be assigned.
756  * @exception AsyncQueuePopError If the queue is empty when a pop is
757  * attempted, this method will throw AsyncQueuePopError. It might
758  * also throw if the copy assignment operator of the queue item might
759  * throw. In order to complete pop operations atomically under a
760  * single lock and to retain strong exception safety, the object into
761  * which the popped data is to be placed is passed as an argument by
762  * reference (this avoids a copy from a temporary object after the
763  * data has been extracted from the queue, which would occur if the
764  * item extracted were returned by value). It might also throw if the
765  * destructor of the queue item might throw (but that should never
766  * happen), or if the empty() method of the container type throws
767  * (which would not happen on any sane implementation).
768  */
769  void pop(value_type& obj) {
770  Thread::Mutex::Lock lock{mutex};
771  if (q.empty()) throw AsyncQueuePopError();
772  obj = q.front();
773  q.pop();
774  }
775 
776 /**
777  * Pops an item from the queue using the contained type's move
778  * assignment operator, if it has one. This method is identical to
779  * the pop() method if that type has no move assignment operator.
780  * This method has strong exception safety if the container is a
781  * std::deque or std::list container (the default is std::list),
782  * provided the destructor of a contained item does not throw and the
783  * move assignment operator of a contained item has strong exception
784  * safety. It is thread safe. Use this method in preference to the
785  * pop() method if it is known that the contained items' move
786  * assignment operator does not throw or is strongly exception safe,
787  * or if the use case does not require strong exception safety. This
788  * method (or the move_pop_basic() method) must be used in place of
789  * the pop() method if the contained type has a move assignment
790  * operator but no copy assignment operator (such as a std::unique_ptr
791  * object).
792  * @param obj A value type reference to which the item at the front of
793  * the queue will be move assigned.
794  * @exception AsyncQueuePopError If the queue is empty when a pop is
795  * attempted, this method will throw AsyncQueuePopError. It might
796  * also throw if the move assignment operator of the queue item might
797  * throw, or if it has no move assignment operator and its copy
798  * assignment operator throws. In order to complete pop operations
799  * atomically under a single lock and to retain strong exception
800  * safety, the object into which the popped data is to be placed is
801  * passed as an argument by reference (this avoids a move from a
802  * temporary object after the data has been extracted from the queue,
803  * which would occur if the item extracted were returned by value).
804  * It might also throw if the destructor of the queue item might throw
805  * (but that should never happen), or if the empty() method of the
806  * container type throws (which would not happen on any sane
807  * implementation).
808  *
809  * Since 2.0.11
810  */
811  void move_pop(value_type& obj) {
812  Thread::Mutex::Lock lock{mutex};
813  if (q.empty()) throw AsyncQueuePopError();
814  obj = std::move(q.front());
815  q.pop();
816  }
817 
818 /**
819  * Pops an item from the queue using the contained type's move
820  * assignment operator, if it has one, or if not using its copy
821  * assignment operator. This method is only available where the
822  * queue's container is a std::list object (which is the default), and
823  * does the same as the move_pop() method except that when popping the
824  * only thing which is done to the queue's container's internal state
825  * within the queue object's mutex is to swap some pointers: in
826  * particular, deallocation of the list node at the front of the queue
827  * occurs outside that mutex, as does assignment to this method's
828  * argument. Given that, if the queue's container is a list, any new
829  * node is also constructed outside the mutex when pushing or
830  * emplacing an item onto the queue, this minimizes contention between
831  * threads: it gets as close to lock-free performance as it is
832  * possible to get with the standard containers.
833  *
834  * However this minimizing of contention comes at a cost, which is
835  * that if the contained item's move assignment operator (or if it has
836  * none, its copy assignment operator) throws, then only the basic
837  * exception guarantee is offered (hence the name of this method).
838  * This means that although the AsyncQueueDispatch object would be
839  * left in a valid state in the event of such throwing, the item at
840  * the front of the queue would be lost. As in the case of the pop()
841  * and move_pop() methods, in addition only the basic exception
842  * guarantee is offered if the destructor of the contained item
843  * throws. Only use this method if the queue's container is a
844  * std::list object, and if either it is known that the contained
845  * item's move assignment operator (or if it has none, its copy
846  * assignment operator) does not throw, or the use case does not
847  * require strong exception safety. This method is thread safe.
848  *
849  * If this method is called for an AsyncQueueDispatch object whose
850  * container is not a std::list object, it will hand off to the
851  * move_pop() method, which is separately documented.
852  * @param obj A value type reference to which the item at the front of
853  * the queue will be move assigned.
854  * @exception AsyncQueuePopError If the queue is empty when a pop is
855  * attempted, this method will throw AsyncQueuePopError. It might
856  * also throw if the move assignment operator of the queue item might
857  * throw or it has no move assignment operator and its copy assignment
858  * operator throws (in which case only the basic exception guarantee
859  * is offered). It might also throw if the destructor of the queue
860  * item might throw (but that should never happen), if the empty()
861  * method of the container type throws (which would not happen on any
862  * sane implementation) or if the constructor of the implementation's
863  * list allocator throws (which would be highly unusual). In the
864  * event of any of the last two throwing, the strong exception
865  * guarantee is offered.
866  *
867  * Since 2.0.26
868  */
869 // See the specialisation for lists for the implementation of this
870 // method. For queues which do not use a list as their container,
871 // this hands off to move_pop().
872  void move_pop_basic(value_type& obj){
873  move_pop(obj);
874  }
875 
876 /**
877  * Pops an item from the queue. If the queue is empty, it will block
878  * until an item becomes available. If it blocks, the wait comprises
879  * a cancellation point. This method is cancellation safe if the
880  * stack unwinds on cancellation, as cancellation is blocked while the
881  * queue is being operated on after coming out of a wait. This method
882  * has strong exception safety if the container is a std::deque or
883  * std::list container (the default is std::list), provided the
884  * destructor of a contained item does not throw. It is thread safe.
885  * @param obj A value type reference to which the item at the front of
886  * the queue will be assigned. This method might throw if the copy
887  * assignment operator of the queue item might throw. In order to
888  * complete pop operations atomically under a single lock and to
889  * retain strong exception safety, the object into which the popped
890  * data is to be placed is passed as an argument by reference (this
891  * avoids a copy from a temporary object after the data has been
892  * extracted from the queue, which would occur if the item extracted
893  * were returned by value). It might also throw if the destructor of
894  * the queue item might throw (but that should never happen), or if
895  * the empty() method of the container type throws (which would not
896  * happen on any sane implementation).
897  */
898  void pop_dispatch(value_type& obj) {
899  Thread::Mutex::Lock lock{mutex};
900  while (q.empty()) cond.wait(mutex);
902  obj = q.front();
903  q.pop();
904  }
905 
906 /**
907  * Pops an item from the queue using the contained type's move
908  * assignment operator, if it has one (this method is identical to the
909  * pop_dispatch() method if that type has no move assignment
910  * operator). If the queue is empty, it will block until an item
911  * becomes available. If it blocks, the wait comprises a cancellation
912  * point. This method is cancellation safe if the stack unwinds on
913  * cancellation, as cancellation is blocked while the queue is being
914  * operated on after coming out of a wait. This method has strong
915  * exception safety if the container is a std::deque or std::list
916  * container (the default is std::list), provided the destructor of a
917  * contained item does not throw and the move assignment operator of a
918  * contained item has strong exception safety. It is thread safe.
919  * Use this method in preference to the pop_dispatch() method if it is
920  * known that the contained items' move assignment operator does not
921  * throw or is strongly exception safe, or if the use case does not
922  * require strong exception safety. This method (or the
923  * move_pop_dispatch_basic() method) must be used in place of the
924  * pop_dispatch() method if the contained type has a move assignment
925  * operator but no copy assignment operator (such as a std::unique_ptr
926  * object).
927  * @param obj A value type reference to which the item at the front of
928  * the queue will be move assigned. This method might throw if the
929  * move assignment operator of the queue item might throw, or if it
930  * has no move assignment operator and its copy assignment operator
931  * throws. In order to complete pop operations atomically under a
932  * single lock and to retain strong exception safety, the object into
933  * which the popped data is to be placed is passed as an argument by
934  * reference (this avoids a move from a temporary object after the
935  * data has been extracted from the queue, which would occur if the
936  * item extracted were returned by value). It might also throw if the
937  * destructor of the queue item might throw (but that should never
938  * happen), or if the empty() method of the container type throws
939  * (which would not happen on any sane implementation).
940  *
941  * Since 2.0.11
942  */
943  void move_pop_dispatch(value_type& obj) {
944  Thread::Mutex::Lock lock{mutex};
945  while (q.empty()) cond.wait(mutex);
947  obj = std::move(q.front());
948  q.pop();
949  }
950 
951 /**
952  * Pops an item from the queue using the contained type's move
953  * assignment operator, if it has one, or if not using its copy
954  * assignment operator. This method is only available where the
955  * queue's container is a std::list object (which is the default), and
956  * does the same as the move_pop_dispatch() method except that when
957  * popping the only thing which is done to the queue's container's
958  * internal state within the queue object's mutex is to swap some
959  * pointers: in particular, deallocation of the list node at the front
960  * of the queue occurs outside that mutex, as does assignment to this
961  * method's argument. Given that, if the queue's container is a list,
962  * any new node is also constructed outside the mutex when pushing or
963  * emplacing an item onto the queue, this minimizes contention between
964  * threads: it gets as close to lock-free performance as it is
965  * possible to get with the standard containers.
966  *
967  * However this minimizing of contention comes at a cost, which is
968  * that if the contained item's move assignment operator (or if it has
969  * none, its copy assignment operator) throws, then only the basic
970  * exception guarantee is offered (hence the name of this method).
971  * This means that although the AsyncQueueDispatch object would be
972  * left in a valid state in the event of such throwing, the item at
973  * the front of the queue would be lost. As in the case of the
974  * pop_dispatch() and move_pop_dispatch() methods, in addition only
975  * the basic exception guarantee is offered if the destructor of the
976  * contained item throws. Only use this method if the queue's
977  * container is a std::list object, and if either it is known that the
978  * contained item's move assignment operator (or if it has none, its
979  * copy assignment operator) does not throw, or the use case does not
980  * require strong exception safety. This method is thread safe.
981  *
982  * If the queue is empty, it will block until an item
983  * becomes available. If it blocks, the wait comprises a cancellation
984  * point. This method is cancellation safe if the stack unwinds on
985  * cancellation, as cancellation is blocked while the queue is being
986  * operated on after coming out of a wait.
987  *
988  * If this method is called for an AsyncQueueDispatch object whose
989  * container is not a std::list object, it will hand off to the
990  * move_pop_dispatch() method, which is separately documented.
991  * @param obj A value type reference to which the item at the front of
992  * the queue will be move assigned. This method might throw if the
993  * move assignment operator of the queue item might throw or it has no
994  * move assignment operator and its copy assignment operator throws
995  * (in which case only the basic exception guarantee is offered). It
996  * might also throw if the destructor of the queue item might throw
997  * (but that should never happen), if the empty() method of the
998  * container type throws (which would not happen on any sane
999  * implementation) or if the constructor of the implementation's list
1000  * allocator throws (which would be highly unusual). In the event of
1001  * any of the last two throwing, the strong exception guarantee is
1002  * offered.
1003  *
1004  * Since 2.0.26
1005  */
1006 // See the specialisation for lists for the implementation of this
1007 // method. For queues which do not use a list as their container,
1008 // this hands off to move_pop_dispatch().
1009  void move_pop_dispatch_basic(value_type& obj) {
1010  move_pop_dispatch(obj);
1011  }
1012 
1013 /**
1014  * Pops an item from the queue. If the queue is empty, it will block
1015  * until an item becomes available or until the timeout expires. If
1016  * it blocks, the wait comprises a cancellation point. This method is
1017  * cancellation safe if the stack unwinds on cancellation, as
1018  * cancellation is blocked while the queue is being operated on after
1019  * coming out of a wait. This method has strong exception safety if
1020  * the container is a std::deque or std::list container (the default
1021  * is std::list), provided the destructor of a contained item does not
1022  * throw. It is thread safe.
1023  * @param obj A value type reference to which the item at the front of
1024  * the queue will be assigned. This method might throw if the copy
1025  * assignment operator of the queue item might throw. In order to
1026  * complete pop operations atomically under a single lock and to
1027  * retain strong exception safety, the object into which the popped
1028  * data is to be placed is passed as an argument by reference (this
1029  * avoids a copy from a temporary object after the data has been
1030  * extracted from the queue, which would occur if the item extracted
1031  * were returned by value). It might also throw if the destructor of
1032  * the queue item might throw (but that should never happen), or if
1033  * the empty() method of the container type throws (which would not
1034  * happen on any sane implementation).
1035  * @param millisec The timeout interval, in milliseconds.
1036  * @return If the timeout expires without an item becoming available,
1037  * the method will return true. If an item from the queue is
1038  * extracted, it returns false.
1039  */
1040  bool pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1041  timespec ts;
1042  Thread::Cond::get_abs_time(ts, millisec);
1043  Thread::Mutex::Lock lock{mutex};
1044  while (q.empty()) {
1045  if (cond.timed_wait(mutex, ts)) return true;
1046  }
1048  obj = q.front();
1049  q.pop();
1050  return false;
1051  }
1052 
1053 /**
1054  * Pops an item from the queue using the contained type's move
1055  * assignment operator, if it has one (this method is identical to the
1056  * pop_timed_dispatch() method if that type has no move assignment
1057  * operator). If the queue is empty, it will block until an item
1058  * becomes available or until the timeout expires. If it blocks, the
1059  * wait comprises a cancellation point. This method is cancellation
1060  * safe if the stack unwinds on cancellation, as cancellation is
1061  * blocked while the queue is being operated on after coming out of a
1062  * wait. This method has strong exception safety if the container is
1063  * a std::deque or std::list container (the default is std::list),
1064  * provided the destructor of a contained item does not throw and the
1065  * move assignment operator of a contained item has strong exception
1066  * safety. It is thread safe. Use this method in preference to the
1067  * pop_timed_dispatch() method if it is known that the contained
1068  * items' move assignment operator does not throw or is strongly
1069  * exception safe, or if the use case does not require strong
1070  * exception safety. This method (or the
1071  * move_pop_timed_dispatch_basic() method) must be used in place of
1072  * the pop_timed_dispatch() method if the contained type has a move
1073  * assignment operator but no copy assignment operator (such as a
1074  * std::unique_ptr object).
1075  * @param obj A value type reference to which the item at the front of
1076  * the queue will be move assigned. This method might throw if the
1077  * move assignment operator of the queue item might throw, or if it
1078  * has no move assignment operator and its copy assignment operator
1079  * throws. In order to complete pop operations atomically under a
1080  * single lock and to retain strong exception safety, the object into
1081  * which the popped data is to be placed is passed as an argument by
1082  * reference (this avoids a move from a temporary object after the
1083  * data has been extracted from the queue, which would occur if the
1084  * item extracted were returned by value). It might also throw if the
1085  * destructor of the queue item might throw (but that should never
1086  * happen), or if the empty() method of the container type throws
1087  * (which would not happen on any sane implementation).
1088  * @param millisec The timeout interval, in milliseconds.
1089  * @return If the timeout expires without an item becoming available,
1090  * the method will return true. If an item from the queue is
1091  * extracted, it returns false.
1092  *
1093  * Since 2.0.11
1094  */
1095  bool move_pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1096  timespec ts;
1097  Thread::Cond::get_abs_time(ts, millisec);
1098  Thread::Mutex::Lock lock{mutex};
1099  while (q.empty()) {
1100  if (cond.timed_wait(mutex, ts)) return true;
1101  }
1103  obj = std::move(q.front());
1104  q.pop();
1105  return false;
1106  }
1107 
1108 /**
1109  * Pops an item from the queue using the contained type's move
1110  * assignment operator, if it has one, or if not using its copy
1111  * assignment operator. This method is only available where the
1112  * queue's container is a std::list object (which is the default), and
1113  * does the same as the move_pop_timed_dispatch() method except that
1114  * when popping the only thing which is done to the queue's
1115  * container's internal state within the queue object's mutex is to
1116  * swap some pointers: in particular, deallocation of the list node at
1117  * the front of the queue occurs outside that mutex, as does
1118  * assignment to this method's argument. Given that, if the queue's
1119  * container is a list, any new node is also constructed outside the
1120  * mutex when pushing or emplacing an item onto the queue, this
1121  * minimizes contention between threads: it gets as close to lock-free
1122  * performance as it is possible to get with the standard containers.
1123  *
1124  * However this minimizing of contention comes at a cost, which is
1125  * that if the contained item's move assignment operator (or if it has
1126  * none, its copy assignment operator) throws, then only the basic
1127  * exception guarantee is offered (hence the name of this method).
1128  * This means that although the AsyncQueueDispatch object would be
1129  * left in a valid state in the event of such throwing, the item at
1130  * the front of the queue would be lost. As in the case of the
1131  * pop_timed_dispatch() and move_pop_timed_dispatch() methods, in
1132  * addition only the basic exception guarantee is offered if the
1133  * destructor of the contained item throws. Only use this method if
1134  * the queue's container is a std::list object, and if either it is
1135  * known that the contained item's move assignment operator (or if it
1136  * has none, its copy assignment operator) does not throw, or the use
1137  * case does not require strong exception safety. This method is
1138  * thread safe.
1139  *
1140  * If the queue is empty, it will block until an item becomes
1141  * available or until the timeout expires. If it blocks, the wait
1142  * comprises a cancellation point. This method is cancellation safe
1143  * if the stack unwinds on cancellation, as cancellation is blocked
1144  * while the queue is being operated on after coming out of a wait.
1145  *
1146  * If this method is called for an AsyncQueueDispatch object whose
1147  * container is not a std::list object, it will hand off to the
1148  * move_pop_timed_dispatch() method, which is separately documented.
1149  * @param obj A value type reference to which the item at the front of
1150  * the queue will be move assigned. This method might throw if the
1151  * move assignment operator of the queue item might throw or it has no
1152  * move assignment operator and its copy assignment operator throws
1153  * (in which case only the basic exception guarantee is offered). It
1154  * might also throw if the destructor of the queue item might throw
1155  * (but that should never happen), if the empty() method of the
1156  * container type throws (which would not happen on any sane
1157  * implementation) or if the constructor of the implementation's list
1158  * allocator throws (which would be highly unusual). In the event of
1159  * any of the last two throwing, the strong exception guarantee is
1160  * offered.
1161  * @param millisec The timeout interval, in milliseconds.
1162  * @return If the timeout expires without an item becoming available,
1163  * the method will return true. If an item from the queue is
1164  * extracted, it returns false.
1165  *
1166  * Since 2.0.26
1167  */
1168 // See the specialisation for lists for the implementation of this
1169 // method. For queues which do not use a list as their container,
1170 // this hands off to move_pop_timed_dispatch().
1171  bool move_pop_timed_dispatch_basic(value_type& obj, unsigned int millisec) {
1172  return move_pop_timed_dispatch(obj, millisec);
1173  }
1174 
1175 /**
1176  * Discards the item at the front of the queue. This method has
1177  * strong exception safety if the container is a std::deque or
1178  * std::list container (the default is std::list), provided the
1179  * destructor of a contained item does not throw. It is thread safe.
1180  * @exception AsyncQueuePopError If the queue is empty when a pop is
1181  * attempted, this method will throw AsyncQueuePopError. It might
1182  * also throw if the destructor of the queue item might throw (but
1183  * that should never happen), or if the empty() method of the
1184  * container type throws (which would not happen on any sane
1185  * implementation).
1186  */
1187  void pop() {
1188  Thread::Mutex::Lock lock{mutex};
1189  if (q.empty()) throw AsyncQueuePopError();
1190  q.pop();
1191  }
1192 
1193 /**
1194  * @return Whether the queue is empty. It will not throw assuming
1195  * that the empty() method of the container type does not throw, as it
1196  * will not on any sane implementation.
1197  * @note This method is thread safe, but the return value may not be
1198  * valid if another thread has pushed to or popped from the queue
1199  * before the value returned by the method is acted on. It is
1200  * provided as a utility, but may not be meaningful, depending on the
1201  * intended usage.
1202  */
1203  bool empty() const {
1204  Thread::Mutex::Lock lock{mutex};
1205  return q.empty();
1206  }
1207 
1208 /**
1209  * @return The number of items currently in the queue. It will not
1210  * throw assuming that the size() method of the container type does
1211  * not throw, as it will not on any sane implementation.
1212  * @note This method is thread safe, but the return value may not be
1213  * valid if another thread has pushed to or popped from the queue
1214  * before the value returned by the method is acted on. It is
1215  * provided as a utility, but may not be meaningful, depending on the
1216  * intended usage.
1217  *
1218  * Since 2.0.8
1219  */
1220  size_type size() const {
1221  Thread::Mutex::Lock lock{mutex};
1222  return q.size();
1223  }
1224 
1225 /**
1226  * Swaps the contents of 'this' and 'other'. It will not throw
1227  * assuming that the swap method of the container type does not throw
1228  * (which the C++11/14 standard requires not to happen with the
1229  * standard sequence containers). It is thread safe and the swap is
1230  * thread-wise atomic. A non-class function
1231  * Cgu::swap(Cgu::AsyncQueueDispatch&, Cgu::AsyncQueueDispatch&)
1232  * method is also provided which will call this method.
1233  * @param other The object to be swapped with this one.
1234  * @note An object swapped does not, by virtue of the swap, inherit
1235  * any threads waiting on the other one. However if threads were
1236  * waiting on a swapped object prior to the swap, and it acquires
1237  * items by virtue of the swap, the waiting threads will unblock and
1238  * extract those items.
1239  *
1240  * Since 2.0.8
1241  */
1242  void swap(AsyncQueueDispatch& other) {
1243  if (this != &other) {
1244  lock2(mutex, other.mutex); // doesn't throw
1246  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
1247  q.swap(other.q);
1248  if (!q.empty()) cond.broadcast();
1249  if (!other.q.empty()) other.cond.broadcast();
1250  }
1251  }
1252 
1253 /**
1254  * The copy assignment operator is strongly exception safe with the
1255  * standard sequence containers (it uses copy and swap). It is also
1256  * thread safe, as it safely locks both the assignor's and assignee's
1257  * mutex to provide a thread-wise atomic assignment.
1258  * @param rhs The assignor.
1259  * @return The AsyncQueueDispatch object after assignment.
1260  * @exception std::bad_alloc The copy constructor of the queue's
1261  * container type, and so this assignment operator, might throw
1262  * std::bad_alloc if memory is exhausted and the system throws in that
1263  * case. This assignment operator will also throw if the copy
1264  * constructor of the queue's container type throws any other
1265  * exceptions, including if any copy or move constructor or copy or
1266  * move assignment operator of a contained item throws.
1267  * @exception Thread::MutexError This assignment operator might
1268  * throw Thread::MutexError if initialization of a transitional
1269  * object's contained mutex fails. (It is often not worth checking
1270  * for this, as it means either memory is exhausted or pthread has run
1271  * out of other resources to create new mutexes.)
1272  * @exception Thread::CondError This assignment operator might throw
1273  * Thread::CondError if initialisation of a transitional object's
1274  * contained condition variable fails. (It is often not worth
1275  * checking for this, as it means either memory is exhausted or
1276  * pthread has run out of other resources to create new condition
1277  * variables.)
1278  * @note The assignee does not, by virtue of the assignment, inherit
1279  * any threads waiting on the assignor. However, if prior to the
1280  * assignment threads were waiting on the assignee and the assignee
1281  * acquires items from the assignor as a result of the assignment, the
1282  * waiting threads will unblock and extract those items.
1283  *
1284  * Since 2.0.8
1285  */
1287  if (this != &rhs) {
1288  lock2(mutex, rhs.mutex); // doesn't throw
1290  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1291  std::queue<T, Container> temp{rhs.q};
1292  q.swap(temp);
1293  if (!q.empty()) cond.broadcast();
1294  }
1295  return *this;
1296  }
1297 
1298 /**
1299  * This move assignment operator is thread safe as regards the
1300  * assignee (the object moved to), but no synchronization is carried
1301  * out with respect to the rvalue assignor/movant. This is because
1302  * temporaries are only visible and accessible in the thread carrying
1303  * out the move operation and synchronization for them would represent
1304  * pointless overhead. In a case where the user uses std::move to
1305  * force a move from a named object, and that named object's lifetime
1306  * is managed by (or the object is otherwise accessed by) a different
1307  * thread than the one making the move, the user must carry out her
1308  * own synchronization with respect to that different thread, both to
1309  * ensure that a consistent view of the the named object is obtained
1310  * and because that object will be mutated by the move. This method
1311  * invokes std::queue's move assignment operator, and therefore has
1312  * the same exception safety as the standard library's implementation
1313  * of that operator. It will not normally throw unless a custom
1314  * allocator is used which throws on move assignment, or the
1315  * destructor of a contained item throws.
1316  * @param rhs The assignor/movant.
1317  * @return The AsyncQueueDispatch object after move assignment.
1318  * @note The assignee does not, by virtue of the move, inherit any
1319  * threads waiting on the assignor/movant. However, if prior to the
1320  * move threads were waiting on the assignee and the assignee acquires
1321  * items from the assignor/movant as a result of the move, from
1322  * version 2.0.9 the waiting threads will unblock and extract those
1323  * items (such unblocking on move assignment did not happen with
1324  * version 2.0.8, which was a bug).
1325  *
1326  * Since 2.0.8
1327  */
1329  Thread::Mutex::Lock lock{mutex};
1330  q = std::move(rhs.q);
1331  if (!q.empty()) cond.broadcast();
1332  return *this;
1333  }
1334 
1335 /**
1336  * @exception std::bad_alloc The default constructor might throw this
1337  * exception if memory is exhausted and the system throws in that
1338  * case.
1339  * @exception Thread::MutexError The default constructor might throw
1340  * this exception if initialisation of the contained mutex fails. (It
1341  * is often not worth checking for this, as it means either memory is
1342  * exhausted or pthread has run out of other resources to create new
1343  * mutexes.)
1344  * @exception Thread::CondError The default constructor might throw
1345  * this exception if initialisation of the contained condition
1346  * variable fails. (It is often not worth checking for this, as it
1347  * means either memory is exhausted or pthread has run out of other
1348  * resources to create new condition variables.)
1349  */
1350  AsyncQueueDispatch() = default;
1351 
1352 /**
1353  * As regards thread safety, the move constructor does not synchronize
1354  * with respect to the initializing rvalue. This is because
1355  * temporaries are only visible and accessible in the thread carrying
1356  * out the move operation and synchronization for them would represent
1357  * pointless overhead. In a case where a user uses std::move to force
1358  * a move from a named object, and that named object's lifetime is
1359  * managed by (or the object is otherwise accessed by) a different
1360  * thread than the one making the move, the user must carry out her
1361  * own synchronization with respect to that different thread, both to
1362  * ensure that a consistent view of the the named object is obtained
1363  * and because that object will be mutated by the move.
1364  * @param rhs The AsyncQueueDispatch object to be moved.
1365  * @exception Thread::MutexError The move constructor might throw
1366  * Thread::MutexError if initialization of the contained mutex fails.
1367  * (It is often not worth checking for this, as it means either memory
1368  * is exhausted or pthread has run out of other resources to create
1369  * new mutexes.) It might also throw if the queue's container type's
1370  * move constructor might throw, but it should not do that unless a
1371  * custom allocator is in use.
1372  * @exception Thread::CondError The move constructor might throw this
1373  * exception if initialisation of the contained condition variable
1374  * fails. (It is often not worth checking for this, as it means
1375  * either memory is exhausted or pthread has run out of other
1376  * resources to create new condition variables.) It might also throw
1377  * if the queue's container type's move constructor might throw, but
1378  * it should not do that unless a custom allocator is in use.
1379  * @note If this constructor throws Thread::MutexError or
1380  * Thread::CondError, and a named object is moved using std::move,
1381  * this constructor is not strongly exception safe (items in the moved
1382  * queue will be lost). Fixing this efficiently requires changing the
1383  * order of construction of data members of this class, which cannot
1384  * be done without an ABI break for this library as it would alter
1385  * object layout: this is therefore fixed in the 2.2 series of the
1386  * library but not in this series. As noted above, in most cases the
1387  * possibility of Thread::MutexError or Thread::CondError throwing can
1388  * be ignored, but where that is not the case and strong exception
1389  * safety is wanted, the user should either not employ std::move with
1390  * named objects when invoking this class's constructors, or should
1391  * construct an AsyncQueueDispatch object using the default
1392  * constructor and then move assign to it.
1393  *
1394  * Since 2.0.8
1395  */
1396  AsyncQueueDispatch(AsyncQueueDispatch&& rhs): q(std::move(rhs.q)) {}
1397 
1398 /**
1399  * The copy constructor is thread safe, as it locks the initializing
1400  * object's mutex to obtain a consistent view of it.
1401  * @param rhs The AsyncQueueDispatch object to be copied.
1402  * @exception std::bad_alloc The copy constructor of the queue's
1403  * container type, and so this constructor, might throw std::bad_alloc
1404  * if memory is exhausted and the system throws in that case. It will
1405  * also throw if the copy constructor of the queue's container type
1406  * throws any other exceptions, including if any copy or move
1407  * constructor or copy or move assignment operator of a contained item
1408  * throws.
1409  * @exception Thread::MutexError The copy constructor might throw
1410  * Thread::MutexError if initialization of the contained mutex fails.
1411  * (It is often not worth checking for this, as it means either memory
1412  * is exhausted or pthread has run out of other resources to create
1413  * new mutexes.)
1414  * @exception Thread::CondError The copy constructor might throw this
1415  * exception if initialisation of the contained condition variable
1416  * fails. (It is often not worth checking for this, as it means
1417  * either memory is exhausted or pthread has run out of other
1418  * resources to create new condition variables.)
1419  *
1420  * Since 2.0.8
1421  */
1422  // we use the comma operator here to lock the mutex and call the
1423  // copy constructor: the lock will be retained until the end of the
1424  // full expression in which it is lexically situated, namely until
1425  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
1427  q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1428 
1429 /**
1430  * The destructor does not throw unless the destructor of a contained
1431  * item throws. It is thread safe (any thread may delete the
1432  * AsyncQueueDispatch object). Destroying an AsyncQueueDispatch
1433  * object on which another thread is currently blocked results in
1434  * undefined behavior.
1435  */
1437  // lock and unlock the mutex in the destructor so that we have an
1438  // acquire operation to ensure that when the std::queue object is
1439  // destroyed memory is synchronised, so any thread may destroy the
1440  // AsyncQueueDispatch object
1441  Thread::Mutex::Lock lock{mutex};
1442  }
1443 
1444 /* Only has effect if --with-glib-memory-slices-compat or
1445  * --with-glib-memory-slices-no-compat option picked */
1447 };
1448 
1449 /**
1450  * Swaps the contents of two AsyncQueue objects. It will not throw
1451  * assuming that the swap method of the container type does not throw
1452  * (which the C++11/13 standard requires not to happen with the
1453  * standard sequence containers). It is thread safe and the swap is
1454  * thread-wise atomic.
1455  * @param q1 An object to be swapped with the other.
1456  * @param q2 An object to be swapped with the other.
1457  * @note Calling std::swap on AsyncQueue objects is thread safe but
1458  * does not provide a thread-wise atomic swap (the swapped objects may
1459  * not be mirror images if during the execution of std::swap's default
1460  * algorithm one of them has been modified), although in many cases
1461  * that doesn't matter. If swap() is called without a namespace
1462  * qualifier, argument dependent look-up will pick this one correctly.
1463  *
1464  * Since 2.0.8
1465  */
1466 template <class T, class Container>
1469  q1.swap(q2);
1470 }
1471 
1472 /**
1473  * Swaps the contents of two AsyncQueueDispatch objects. It will not
1474  * throw assuming that the swap method of the container type does not
1475  * throw (which the C++11/13 standard requires not to happen with the
1476  * standard sequence containers). It is thread safe and the swap is
1477  * thread-wise atomic.
1478  * @param q1 An object to be swapped with the other.
1479  * @param q2 An object to be swapped with the other.
1480  * @note 1. An object swapped does not, by virtue of the swap, inherit
1481  * any threads waiting on the other one. However if threads were
1482  * waiting on a swapped object prior to the swap, and it acquires
1483  * items by virtue of the swap, the waiting threads will unblock and
1484  * extract those items.
1485  * @note 2. Calling std::swap on AsyncQueueDispatch objects is thread
1486  * safe but does not provide a thread-wise atomic swap (the swapped
1487  * objects may not be mirror images if during the execution of
1488  * std::swap's default algorithm one of them has been modified),
1489  * although in many cases that doesn't matter. If swap() is called
1490  * without a namespace qualifier, argument dependent look-up will pick
1491  * this one correctly.
1492  *
1493  * Since 2.0.8
1494  */
1495 template <class T, class Container>
1498  q1.swap(q2);
1499 }
1500 
1501 #if defined(CGU_USE_INHERITABLE_QUEUE) && !defined(DOXYGEN_PARSING)
1502 
1503 /* This is a specialization of AsyncQueue for std::list objects, which
1504  uses std::list::splice() to push or emplace a new item on the
1505  queue. This means that allocation for the push or emplacement
1506  occurs outside the mutex, so reducing contention (a tip from a talk
1507  by Sean Parent of Adobe). This is first available in version
1508  2.0.20.
1509  */
1510 template <class T, class Allocator>
1511 class AsyncQueue<T, std::list<T, Allocator> > {
1512 public:
1513  typedef std::list<T, Allocator> Container;
1514  typedef typename Container::value_type value_type;
1515  typedef typename Container::size_type size_type;
1516  typedef Container container_type;
1517 private:
1518  // 23.6.3.1 of C++11 requires std::queue to have a protected
1519  // container member called 'c' for the purposes of derivation. This
1520  // specialisation will have the same binary layout as the
1521  // unspecialized version on any practical implementation: all we do
1522  // is add splice_end() and unsplice_beginning() members
1523  class Q: public std::queue<T, Container> {
1524  public:
1525  void splice_end(Container&& lst) {
1526  this->c.splice(this->c.end(), std::move(lst));
1527  }
1528  void unsplice_beginning(Container& lst) {
1529  lst.splice(lst.begin(), this->c, this->c.begin());
1530  }
1531  } q;
1532  mutable Thread::Mutex mutex;
1533 
1534 // TODO: at the next ABI break make this method explicitly static
1535  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1536  m1.lock();
1537  for(;;) {
1538  if (!m2.trylock()) {
1539  return;
1540  }
1541  m1.unlock();
1542  // spin nicely
1543 #ifdef CGU_USE_SCHED_YIELD
1544  sched_yield();
1545 #else
1546  usleep(10);
1547 #endif
1548  m1.lock();
1549  }
1550  }
1551 public:
1552  void push(const value_type& obj) {
1553  Container temp{obj};
1554  Thread::Mutex::Lock lock{mutex};
1555  // splice_end doesn't throw
1556  q.splice_end(std::move(temp));
1557  }
1558 
1559  void push(value_type&& obj) {
1560  // although move intialisation of a std::list object via an
1561  // initializer list with a single element is almost certain to be
1562  // strongly exception safe, it is not mandated by the standard so
1563  // use push_back() (which is required to be strongly exception
1564  // safe)
1565  Container temp;
1566  temp.push_back(std::move(obj));
1567  Thread::Mutex::Lock lock{mutex};
1568  // splice_end doesn't throw
1569  q.splice_end(std::move(temp));
1570  }
1571 
1572  template<class... Args>
1573  void emplace(Args&&... args) {
1574  Container temp;
1575  temp.emplace_back(std::forward<Args>(args)...);
1576  Thread::Mutex::Lock lock{mutex};
1577  // splice_end doesn't throw
1578  q.splice_end(std::move(temp));
1579  }
1580 
1581  void pop(value_type& obj) {
1582  Thread::Mutex::Lock lock{mutex};
1583  if (q.empty()) throw AsyncQueuePopError();
1584  obj = q.front();
1585  q.pop();
1586  }
1587 
1588  void move_pop(value_type& obj) {
1589  Thread::Mutex::Lock lock{mutex};
1590  if (q.empty()) throw AsyncQueuePopError();
1591  obj = std::move(q.front());
1592  q.pop();
1593  }
1594 
1595  void move_pop_basic(value_type& obj) {
1596  // the standard does not require it, but in practice constructing
1597  // an empty list will not throw unless constructing its allocator
1598  // throws
1599  Container temp;
1600  {
1601  Thread::Mutex::Lock lock{mutex};
1602  if (q.empty()) throw AsyncQueuePopError();
1603  // unsplice_beginning doesn't throw
1604  q.unsplice_beginning(temp);
1605  }
1606  obj = std::move(temp.front());
1607  }
1608 
1609  void pop() {
1610  Thread::Mutex::Lock lock{mutex};
1611  if (q.empty()) throw AsyncQueuePopError();
1612  q.pop();
1613  }
1614 
1615  bool empty() const {
1616  Thread::Mutex::Lock lock{mutex};
1617  return q.empty();
1618  }
1619 
1620  size_type size() const {
1621  Thread::Mutex::Lock lock{mutex};
1622  return q.size();
1623  }
1624 
1625  void swap(AsyncQueue& other) {
1626  if (this != &other) {
1627  lock2(mutex, other.mutex); // doesn't throw
1628  Thread::Mutex::Lock l1{mutex, Thread::locked};
1629  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
1630  q.swap(other.q);
1631  }
1632  }
1633 
1634  AsyncQueue& operator=(const AsyncQueue& rhs) {
1635  if (this != &rhs) {
1636  lock2(mutex, rhs.mutex); // doesn't throw
1637  Thread::Mutex::Lock l1{mutex, Thread::locked};
1638  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1639  Q temp{rhs.q};
1640  q.swap(temp);
1641  }
1642  return *this;
1643  }
1644 
1645  AsyncQueue& operator=(AsyncQueue&& rhs) {
1646  Thread::Mutex::Lock lock{mutex};
1647  q = std::move(rhs.q);
1648  return *this;
1649  }
1650 
1651  AsyncQueue() = default;
1652 
1653  AsyncQueue(AsyncQueue&& rhs): q(std::move(rhs.q)) {}
1654 
1655  AsyncQueue(const AsyncQueue& rhs): q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1656 
1657  ~AsyncQueue() {
1658  Thread::Mutex::Lock lock{mutex};
1659  }
1660 
1662 };
1663 
1664 /* This is a specialization of AsyncQueueDispatch for std::list
1665  objects, which uses std::list::splice() to push or emplace a new
1666  item on the queue. This means that allocation for the push or
1667  emplacement occurs outside the mutex, so reducing contention (a tip
1668  from a talk by Sean Parent of Adobe). This is first available in
1669  version 2.0.20.
1670  */
1671 template <class T, class Allocator>
1672 class AsyncQueueDispatch<T, std::list<T, Allocator> > {
1673 public:
1674  typedef std::list<T, Allocator> Container;
1675  typedef typename Container::value_type value_type;
1676  typedef typename Container::size_type size_type;
1677  typedef Container container_type;
1678 private:
1679  // 23.6.3.1 of C++11 requires std::queue to have a protected
1680  // container member called 'c' for the purposes of derivation. This
1681  // specialisation will have the same binary layout as the
1682  // unspecialized version on any practical implementation: all we do
1683  // is add splice_end() and unsplice_beginning() members
1684  class Q: public std::queue<T, Container> {
1685  public:
1686  void splice_end(Container&& lst) {
1687  this->c.splice(this->c.end(), std::move(lst));
1688  }
1689  void unsplice_beginning(Container& lst) {
1690  lst.splice(lst.begin(), this->c, this->c.begin());
1691  }
1692  } q;
1693  mutable Thread::Mutex mutex;
1694  Thread::Cond cond;
1695 
1696 // TODO: at the next ABI break make this method explicitly static
1697  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
1698  m1.lock();
1699  for(;;) {
1700  if (!m2.trylock()) {
1701  return;
1702  }
1703  m1.unlock();
1704  // spin nicely
1705 #ifdef CGU_USE_SCHED_YIELD
1706  sched_yield();
1707 #else
1708  usleep(10);
1709 #endif
1710  m1.lock();
1711  }
1712  }
1713 public:
1714  void push(const value_type& obj) {
1715  Container temp{obj};
1716  Thread::Mutex::Lock lock{mutex};
1717  // splice_end doesn't throw
1718  q.splice_end(std::move(temp));
1719  cond.signal();
1720  }
1721 
1722  void push(value_type&& obj) {
1723  // although move intialisation of a std::list object via an
1724  // initializer list with a single element is almost certain to be
1725  // strongly exception safe, it is not mandated by the standard so
1726  // use push_back() (which is required to be strongly exception
1727  // safe)
1728  Container temp;
1729  temp.push_back(std::move(obj));
1730  Thread::Mutex::Lock lock{mutex};
1731  // splice_end doesn't throw
1732  q.splice_end(std::move(temp));
1733  cond.signal();
1734  }
1735 
1736  template<class... Args>
1737  void emplace(Args&&... args) {
1738  Container temp;
1739  temp.emplace_back(std::forward<Args>(args)...);
1740  Thread::Mutex::Lock lock{mutex};
1741  // splice_end doesn't throw
1742  q.splice_end(std::move(temp));
1743  cond.signal();
1744  }
1745 
1746  void pop(value_type& obj) {
1747  Thread::Mutex::Lock lock{mutex};
1748  if (q.empty()) throw AsyncQueuePopError();
1749  obj = q.front();
1750  q.pop();
1751  }
1752 
1753  void move_pop(value_type& obj) {
1754  Thread::Mutex::Lock lock{mutex};
1755  if (q.empty()) throw AsyncQueuePopError();
1756  obj = std::move(q.front());
1757  q.pop();
1758  }
1759 
1760  void move_pop_basic(value_type& obj) {
1761  // the standard does not require it, but in practice constructing
1762  // an empty list will not throw unless constructing its allocator
1763  // throws
1764  Container temp;
1765  {
1766  Thread::Mutex::Lock lock{mutex};
1767  if (q.empty()) throw AsyncQueuePopError();
1768  // unsplice_beginning doesn't throw
1769  q.unsplice_beginning(temp);
1770  }
1771  obj = std::move(temp.front());
1772  }
1773 
1774  void pop_dispatch(value_type& obj) {
1775  Thread::Mutex::Lock lock{mutex};
1776  while (q.empty()) cond.wait(mutex);
1777  Thread::CancelBlock b;
1778  obj = q.front();
1779  q.pop();
1780  }
1781 
1782  void move_pop_dispatch(value_type& obj) {
1783  Thread::Mutex::Lock lock{mutex};
1784  while (q.empty()) cond.wait(mutex);
1785  Thread::CancelBlock b;
1786  obj = std::move(q.front());
1787  q.pop();
1788  }
1789 
1790  void move_pop_dispatch_basic(value_type& obj) {
1791  int old_state;
1792  int ignore;
1793  bool cancelstate_restored = false;
1794  try {
1795  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
1796  // the standard does not require it, but in practice
1797  // constructing an empty list will not throw unless constructing
1798  // its allocator throws
1799  Container temp;
1800  pthread_setcancelstate(old_state, &ignore);
1801  cancelstate_restored = true;
1802  Thread::Mutex::TrackLock lock{mutex};
1803  while (q.empty()) cond.wait(mutex);
1804  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ignore);
1805  cancelstate_restored = false;
1806  // unsplice_beginning doesn't throw
1807  q.unsplice_beginning(temp);
1808  lock.unlock();
1809  obj = std::move(temp.front());
1810  pthread_setcancelstate(old_state, &ignore);
1811  }
1812  catch (...) {
1813  // in practice we could only enter here with
1814  // cancelstate_restored set as true if there has been a
1815  // cancellation pseudo-exception (but the code doesn't depend on
1816  // that). We could only enter here with a normal exception if
1817  // the construction of temp has thrown or if a queue element's
1818  // move/copy assignment operator has thrown (but again the code
1819  // doesn't depend on that).
1820  if (!cancelstate_restored) {
1821  pthread_setcancelstate(old_state, &ignore);
1822  }
1823  throw;
1824  }
1825  }
1826 
1827  bool pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1828  timespec ts;
1829  Thread::Cond::get_abs_time(ts, millisec);
1830  Thread::Mutex::Lock lock{mutex};
1831  while (q.empty()) {
1832  if (cond.timed_wait(mutex, ts)) return true;
1833  }
1834  Thread::CancelBlock b;
1835  obj = q.front();
1836  q.pop();
1837  return false;
1838  }
1839 
1840  bool move_pop_timed_dispatch(value_type& obj, unsigned int millisec) {
1841  timespec ts;
1842  Thread::Cond::get_abs_time(ts, millisec);
1843  Thread::Mutex::Lock lock{mutex};
1844  while (q.empty()) {
1845  if (cond.timed_wait(mutex, ts)) return true;
1846  }
1847  Thread::CancelBlock b;
1848  obj = std::move(q.front());
1849  q.pop();
1850  return false;
1851  }
1852 
1853  bool move_pop_timed_dispatch_basic(value_type& obj, unsigned int millisec) {
1854  timespec ts;
1855  Thread::Cond::get_abs_time(ts, millisec);
1856  int old_state;
1857  int ignore;
1858  bool cancelstate_restored = false;
1859  try {
1860  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
1861  // the standard does not require it, but in practice
1862  // constructing an empty list will not throw unless constructing
1863  // its allocator throws
1864  Container temp;
1865  pthread_setcancelstate(old_state, &ignore);
1866  cancelstate_restored = true;
1867  Thread::Mutex::TrackLock lock{mutex};
1868  while (q.empty()) {
1869  if (cond.timed_wait(mutex, ts)) return true;
1870  }
1871  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &ignore);
1872  cancelstate_restored = false;
1873  // unsplice_beginning doesn't throw
1874  q.unsplice_beginning(temp);
1875  lock.unlock();
1876  obj = std::move(temp.front());
1877  pthread_setcancelstate(old_state, &ignore);
1878  return false;
1879  }
1880  catch (...) {
1881  // in practice we could only enter here with
1882  // cancelstate_restored set as true if there has been a
1883  // cancellation pseudo-exception (but the code doesn't depend on
1884  // that). We could only enter here with a normal exception if
1885  // the construction of temp has thrown or if a queue element's
1886  // move/copy assignment operator has thrown (but again the code
1887  // doesn't depend on that).
1888  if (!cancelstate_restored) {
1889  pthread_setcancelstate(old_state, &ignore);
1890  }
1891  throw;
1892  }
1893  }
1894 
1895  void pop() {
1896  Thread::Mutex::Lock lock{mutex};
1897  if (q.empty()) throw AsyncQueuePopError();
1898  q.pop();
1899  }
1900 
1901  bool empty() const {
1902  Thread::Mutex::Lock lock{mutex};
1903  return q.empty();
1904  }
1905 
1906  size_type size() const {
1907  Thread::Mutex::Lock lock{mutex};
1908  return q.size();
1909  }
1910 
1911  void swap(AsyncQueueDispatch& other) {
1912  if (this != &other) {
1913  lock2(mutex, other.mutex); // doesn't throw
1914  Thread::Mutex::Lock l1{mutex, Thread::locked};
1915  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
1916  q.swap(other.q);
1917  if (!q.empty()) cond.broadcast();
1918  if (!other.q.empty()) other.cond.broadcast();
1919  }
1920  }
1921 
1923  if (this != &rhs) {
1924  lock2(mutex, rhs.mutex); // doesn't throw
1925  Thread::Mutex::Lock l1{mutex, Thread::locked};
1926  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
1927  Q temp{rhs.q};
1928  q.swap(temp);
1929  if (!q.empty()) cond.broadcast();
1930  }
1931  return *this;
1932  }
1933 
1935  Thread::Mutex::Lock lock{mutex};
1936  q = std::move(rhs.q);
1937  if (!q.empty()) cond.broadcast();
1938  return *this;
1939  }
1940 
1941  AsyncQueueDispatch() = default;
1942 
1943  AsyncQueueDispatch(AsyncQueueDispatch&& rhs): q(std::move(rhs.q)) {}
1944 
1946  q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
1947 
1949  Thread::Mutex::Lock lock{mutex};
1950  }
1951 
1953 };
1954 
1955 #endif // CGU_USE_INHERITABLE_QUEUE
1956 
1957 } // namespace Cgu
1958 
1959 #endif
int broadcast()
Definition: mutex.h:483
void push(value_type &&obj)
Definition: async_queue.h:217
void pop(value_type &obj)
Definition: async_queue.h:769
void pop()
Definition: async_queue.h:390
size_type size() const
Definition: async_queue.h:1220
void swap(Cgu::AsyncQueue< T, Container > &q1, Cgu::AsyncQueue< T, Container > &q2)
Definition: async_queue.h:1467
~AsyncQueueDispatch()
Definition: async_queue.h:1436
STL namespace.
Container::size_type size_type
Definition: async_queue.h:150
int signal()
Definition: mutex.h:472
void emplace(Args &&...args)
Definition: async_queue.h:743
void pop_dispatch(value_type &obj)
Definition: async_queue.h:898
void move_pop(value_type &obj)
Definition: async_queue.h:313
A wrapper class for pthread condition variables.
Definition: mutex.h:449
AsyncQueue(const AsyncQueue &rhs)
Definition: async_queue.h:583
AsyncQueue()=default
An exception thrown if calling pop() on a AsyncQueue or AsyncQueueDispatch object fails because the q...
Definition: async_queue.h:102
void move_pop_basic(value_type &obj)
Definition: async_queue.h:872
A thread-safe asynchronous queue.
Definition: async_queue.h:147
A thread-safe asynchronous queue with a blocking pop() method.
Definition: async_queue.h:641
void pop()
Definition: async_queue.h:1187
Definition: mutex.h:196
static void get_abs_time(timespec &ts, unsigned int millisec)
void push(value_type &&obj)
Definition: async_queue.h:713
A class enabling the cancellation state of a thread to be controlled.
Definition: thread.h:681
bool move_pop_timed_dispatch(value_type &obj, unsigned int millisec)
Definition: async_queue.h:1095
A scoped locking class for exception safe Mutex locking.
Definition: mutex.h:207
bool move_pop_timed_dispatch_basic(value_type &obj, unsigned int millisec)
Definition: async_queue.h:1171
void move_pop_dispatch_basic(value_type &obj)
Definition: async_queue.h:1009
void move_pop_basic(value_type &obj)
Definition: async_queue.h:374
AsyncQueueDispatch & operator=(AsyncQueueDispatch &&rhs)
Definition: async_queue.h:1328
~AsyncQueue()
Definition: async_queue.h:590
AsyncQueueDispatch(AsyncQueueDispatch &&rhs)
Definition: async_queue.h:1396
virtual const char * what() const
Definition: async_queue.h:103
void push(const value_type &obj)
Definition: async_queue.h:194
int timed_wait(Mutex &mutex, const timespec &abs_time)
Definition: mutex.h:558
AsyncQueue(AsyncQueue &&rhs)
Definition: async_queue.h:558
A wrapper class for pthread mutexes.
Definition: mutex.h:117
void move_pop_dispatch(value_type &obj)
Definition: async_queue.h:943
int unlock()
Definition: mutex.h:170
void pop(value_type &obj)
Definition: async_queue.h:271
AsyncQueue & operator=(AsyncQueue &&rhs)
Definition: async_queue.h:505
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
bool empty() const
Definition: async_queue.h:406
size_type size() const
Definition: async_queue.h:423
Definition: application.h:44
void push(const value_type &obj)
Definition: async_queue.h:689
Container::value_type value_type
Definition: async_queue.h:149
bool pop_timed_dispatch(value_type &obj, unsigned int millisec)
Definition: async_queue.h:1040
AsyncQueueDispatch(const AsyncQueueDispatch &rhs)
Definition: async_queue.h:1426
int trylock()
Definition: mutex.h:157
bool empty() const
Definition: async_queue.h:1203
void move_pop(value_type &obj)
Definition: async_queue.h:811
Container::value_type value_type
Definition: async_queue.h:643
void emplace(Args &&...args)
Definition: async_queue.h:246
AsyncQueueDispatch & operator=(const AsyncQueueDispatch &rhs)
Definition: async_queue.h:1286
void swap(AsyncQueue &other)
Definition: async_queue.h:440
int lock()
Definition: mutex.h:147
Container container_type
Definition: async_queue.h:645
AsyncQueue & operator=(const AsyncQueue &rhs)
Definition: async_queue.h:471
Container container_type
Definition: async_queue.h:151
void swap(AsyncQueueDispatch &other)
Definition: async_queue.h:1242
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Container::size_type size_type
Definition: async_queue.h:644
int wait(Mutex &mutex)
Definition: mutex.h:508