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