c++-gtk-utils
async_queue.h
Go to the documentation of this file.
1 /* Copyright (C) 2006 to 2012 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) method provides the pop()ed element by reference - see the
46  * comments on that method for the reason), except that it has mutex
47  * locking of the data container so as to permit push()ing and
48  * pop()ing from different threads. It is therefore useful for
49  * passing data between threads, perhaps in response to a signal being
50  * emitted from a Notifier object. Passing the data by means of a
51  * SharedLockPtr object, or an IntrusivePtr object referencing data
52  * derived from IntrusiveLockCounter, would be ideal.
53  *
54  * AsyncQueueDispatch is a class which has a blocking pop() method,
55  * which allows it to be waited on by a dedicated event/message
56  * dispatching thread for incoming work (represented by the data
57  * pushed onto the queue). In the same way, it can be used to
58  * implement thread pools, by having threads in the pool waiting on
59  * the queue.
60  *
61  * By default the queues use a std::list object as their container
62  * because in the kind of use mentioned above they are unlikely to
63  * hold many objects but they can be changed to, say, a std::deque
64  * object by specifying it as the second template parameter.
65  */
66 
67 #ifndef CGU_ASYNC_QUEUE_H
68 #define CGU_ASYNC_QUEUE_H
69 
70 #include <queue>
71 #include <list>
72 #include <exception>
73 #include <utility> // for std::move and std::forward
74 #include <algorithm> // for std::swap
75 #include <time.h>
76 
77 #include <c++-gtk-utils/mutex.h>
78 #include <c++-gtk-utils/thread.h>
80 
81 #ifdef CGU_USE_SCHED_YIELD
82 #include <sched.h>
83 #else
84 #include <unistd.h>
85 #endif
86 
87 namespace Cgu {
88 
89 /**
90  * @class AsyncQueuePopError async_queue.h c++-gtk-utils/async_queue.h
91  * @brief An exception thrown if calling pop() on a AsyncQueue or
92  * AsyncQueueDispatch object fails because the queue is empty.
93  * @sa AsyncQueue AsyncQueueDispatch
94  */
95 
96 struct AsyncQueuePopError: public std::exception {
97  virtual const char* what() const throw() {return "AsyncQueuePopError: popping from empty AsyncQueue object\n";}
98 };
99 
100 
101 /**
102  * @class AsyncQueue async_queue.h c++-gtk-utils/async_queue.h
103  * @brief A thread-safe asynchronous queue.
104  * @sa AsyncQueueDispatch AsyncResult
105  *
106  * AsyncQueue is a class which provides some of the functionality of a
107  * std::queue object (but note that the AsyncQueue::pop(value_type&
108  * obj) method provides the pop()ed element by reference - see the
109  * comments on that method for the reason), except that it has mutex
110  * locking of the data container so as to permit push()ing and
111  * pop()ing from different threads. It is therefore useful for
112  * passing data between threads, perhaps in response to a signal being
113  * emitted from a Notifier object. Passing the data by means of a
114  * SharedLockPtr object, or an IntrusivePtr object referencing data
115  * derived from IntrusiveLockCounter, would be ideal.
116  *
117  * By default the queue uses a std::list object as its container
118  * because in the kind of use mentioned above it is unlikely to hold
119  * many objects but it can be changed to, say, a std::deque object by
120  * specifying it as the second template parameter.
121  *
122  * If the library is installed using the
123  * --with-glib-memory-slices-compat or
124  * --with-glib-memory-slices-no-compat configuration options, any
125  * AsyncQueue objects constructed on free store will be constructed in
126  * glib memory slices. This does not affect the queue container
127  * itself: to change the allocator of the C++ container, a custom
128  * allocator type can be provided when the AsyncQueue object is
129  * instantiated offering the standard allocator interface. If glib
130  * memory slices are not used or no AsyncQueue objects are constructed
131  * on free store, it is not necessary to call g_thread_init() before
132  * manipulating or using an AsyncQueue object in multiple threads, but
133  * prior to glib version 2.32 glib itself (and thus glib memory
134  * slices) are not thread safe unless that function has been called.
135  */
136 
137 template <class T, class Container = std::list<T> > class AsyncQueue {
138 public:
139  typedef typename Container::value_type value_type;
140  typedef typename Container::size_type size_type;
141  typedef Container container_type;
142 private:
143 // TODO: put 'q' after 'mutex' at the next ABI break, so move
144 // construction is strongly exception safe
145  std::queue<T, Container> q;
146  mutable Thread::Mutex mutex;
147 
148 // this won't throw: it is for the user to ensure the arguments do not
149 // refer to the same mutex object
150  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
151  m1.lock();
152  for(;;) {
153  if (!m2.trylock()) {
154  return;
155  }
156  m1.unlock();
157  // spin nicely
158 #ifdef CGU_USE_SCHED_YIELD
159  sched_yield();
160 #else
161  usleep(10);
162 #endif
163  m1.lock();
164  }
165  }
166 public:
167 /**
168  * Pushes an item onto the queue. This method has strong exception
169  * safety if the container is a std::list or std::deque container (the
170  * default is std::list), except that if std::deque is used as the
171  * container and the copy constructor, move constructor, assignment
172  * operator or move assignment operator of the queue item throws, it
173  * only gives the basic exception guarantee (and the basic guarantee
174  * is not given by std::deque if the queue item's move constructor
175  * throws and it uses a non-default allocator which does not provide
176  * for it to be CopyInsertable). It is thread safe.
177  * @param obj The item to be pushed onto the queue.
178  * @exception std::bad_alloc The method might throw std::bad_alloc if
179  * memory is exhausted and the system throws in that case. It might
180  * also throw if the copy constructor, move constructor, assignment
181  * operator or move assignment operator of the queue item might throw.
182  */
183  void push(const value_type& obj) {
184  Thread::Mutex::Lock lock{mutex};
185  q.push(obj);
186  }
187 
188 /**
189  * Pushes an item onto the queue. This method has strong exception
190  * safety if the container is a std::list or std::deque container (the
191  * default is std::list), except that if std::deque is used as the
192  * container and the copy constructor, move constructor, assignment
193  * operator or move assignment operator of the queue item throws, it
194  * only gives the basic exception guarantee (and the basic guarantee
195  * is not given by std::deque if the queue item's move constructor
196  * throws and it uses a non-default allocator which does not provide
197  * for it to be CopyInsertable). It is thread safe.
198  * @param obj The item to be pushed onto the queue.
199  * @exception std::bad_alloc The method might throw std::bad_alloc if
200  * memory is exhausted and the system throws in that case. It might
201  * also throw if the copy constructor, move constructor, assignment
202  * operator or move assignment operator of the queue item might throw.
203  *
204  * Since 2.0.0-rc5
205  */
206  void push(value_type&& obj) {
207  Thread::Mutex::Lock lock{mutex};
208  q.push(std::move(obj));
209  }
210 
211 /**
212  * Pushes an item onto the queue by constructing it in place: that is,
213  * by passing to this method the item's constructor's arguments,
214  * rather than the item itself. This method has strong exception
215  * safety if the container is a std::list or std::deque container (the
216  * default is std::list). (Technically, for a std::deque container,
217  * emplace() only offers the same exception guarantees as does push(),
218  * namely only the basic guarantee where a copy or move of the queue
219  * item throws during the call, but the purpose of emplace is to
220  * construct in place and any reasonable implementation will not copy
221  * or move the queue item.) It is thread safe.
222  * @param args The constructor arguments for the item to be pushed
223  * onto the queue.
224  * @exception std::bad_alloc The method might throw std::bad_alloc if
225  * memory is exhausted and the system throws in that case. It might
226  * also throw if the item's constructor (including any of its
227  * constructor arguments) might throw when constructing the item.
228  * @note The constructor of the item pushed onto the queue must not
229  * access any of the methods of the same queue object, or a deadlock
230  * might occur.
231  *
232  * Since 2.0.0-rc5
233  */
234  template<class... Args>
235  void emplace(Args&&... args) {
236  Thread::Mutex::Lock lock{mutex};
237  q.emplace(std::forward<Args>(args)...);
238  }
239 
240 /**
241  * Pops an item from the queue. This method has strong exception
242  * safety if the container is a std::deque or std::list container (the
243  * default is std::list), provided the destructor of a contained item
244  * does not throw. It is thread safe.
245  * @param obj A value type reference to which the item at the front of
246  * the queue will be assigned.
247  * @exception AsyncQueuePopError If the queue is empty when a pop is
248  * attempted, this method will throw AsyncQueuePopError. It might
249  * also throw if the assignment operator of the queue item might
250  * throw. In order to complete pop() operations atomically under a
251  * single lock and to retain strong exception safety, the object into
252  * which the pop()ed data is to be placed is passed as an argument by
253  * reference (this avoids a copy from a temporary object after the
254  * data has been extracted from the queue, which would occur if the
255  * item extracted were returned by value). It might also throw if the
256  * destructor of the queue item might throw (but that should never
257  * happen), or if the empty() method of the container type throws
258  * (which would not happen on any sane implementation).
259  */
260  void pop(value_type& obj) {
261  Thread::Mutex::Lock lock{mutex};
262  if (q.empty()) throw AsyncQueuePopError();
263  obj = q.front();
264  q.pop();
265  }
266 
267 /**
268  * Discards the item at the front of the queue. This method has
269  * strong exception safety if the container is a std::deque or
270  * std::list container (the default is std::list), provided the
271  * destructor of a contained item does not throw. It is thread safe.
272  * @exception AsyncQueuePopError If the queue is empty when a pop is
273  * attempted, this method will throw AsyncQueuePopError. It might
274  * also throw if the destructor of the queue item might throw (but
275  * that should never happen), or if the empty() method of the
276  * container type throws (which would not happen on any sane
277  * implementation).
278  */
279  void pop() {
280  Thread::Mutex::Lock lock{mutex};
281  if (q.empty()) throw AsyncQueuePopError();
282  q.pop();
283  }
284 
285 /**
286  * @return Whether the queue is empty. It will not throw assuming
287  * that the empty() method of the container type does not throw, as it
288  * will not on any sane implementation.
289  * @note This method is thread safe, but the return value may not be
290  * valid if another thread has pushed to or popped from the queue
291  * before the value returned by the method is acted on. It is
292  * provided as a utility, but may not be meaningful, depending on the
293  * intended usage.
294  */
295  bool empty() const {
296  Thread::Mutex::Lock lock{mutex};
297  return q.empty();
298  }
299 
300 /**
301  * @return The number of items currently in the queue. It will not
302  * throw assuming that the size() method of the container type does
303  * not throw, as it will not on any sane implementation.
304  * @note This method is thread safe, but the return value may not be
305  * valid if another thread has pushed to or popped from the queue
306  * before the value returned by the method is acted on. It is
307  * provided as a utility, but may not be meaningful, depending on the
308  * intended usage.
309  *
310  * Since 2.0.8
311  */
312  size_type size() const {
313  Thread::Mutex::Lock lock{mutex};
314  return q.size();
315  }
316 
317 /**
318  * Swaps the contents of 'this' and 'other'. It will not throw
319  * assuming that the swap method of the container type does not throw
320  * (which the C++11 standard requires not to happen with the standard
321  * sequence containers). It is thread safe and the swap is
322  * thread-wise atomic. A non-class function
323  * Cgu::swap(Cgu::AsyncQueue&, Cgu::AsyncQueue&) method is also
324  * provided which will call this method.
325  * @param other The object to be swapped with this one.
326  *
327  * Since 2.0.8
328  */
329  void swap(AsyncQueue& other) {
330  if (this != &other) {
331  lock2(mutex, other.mutex); // doesn't throw
333  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
334  q.swap(other.q);
335  }
336  }
337 
338 /**
339  * The assignment operator is strongly exception safe with the
340  * standard sequence containers (it uses copy and swap). It is also
341  * thread safe, as it safely locks both the assignor's and assignee's
342  * mutex to provide a thread-wise atomic assignment.
343  * @param rhs The assignor.
344  * @return The AsyncQueue object after assignment.
345  * @exception std::bad_alloc The copy constructor of the queue's
346  * container type, and so this assignment operator, might throw
347  * std::bad_alloc if memory is exhausted and the system throws in that
348  * case. This assignment operator will also throw if the copy
349  * constructor of the queue's container type throws any other
350  * exceptions, including if any copy or move constructor or copy or
351  * move assignment operator of a contained item throws.
352  * @exception Thread::MutexError The assignment operator might throw
353  * Thread::MutexError if initialization of a transitional object's
354  * contained mutex fails. (It is often not worth checking for this,
355  * as it means either memory is exhausted or pthread has run out of
356  * other resources to create new mutexes.)
357  *
358  * Since 2.0.8
359  */
361  if (this != &rhs) {
362  lock2(mutex, rhs.mutex); // doesn't throw
364  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
365  std::queue<T, Container> temp{rhs.q};
366  q.swap(temp);
367  }
368  return *this;
369  }
370 
371 /**
372  * This move assignment operator is thread safe as regards the
373  * assignee (the object moved to), but no synchronization is carried
374  * out with respect to the rvalue assignor/movant. This is because
375  * temporaries are only visible and accessible in the thread carrying
376  * out the move operation and synchronization for them would represent
377  * pointless overhead. In a case where the user uses std::move to
378  * force a move from a named object, and that named object's lifetime
379  * is managed by (or the object is otherwise accessed by) a different
380  * thread than the one making the move, the user must carry out her
381  * own synchronization with respect to that different thread, both to
382  * ensure that a consistent view of the the named object is obtained
383  * and because that object will be mutated by the move. This method
384  * invokes std::queue's move assignment operator, and therefore has
385  * the same exception safety as the standard library's implementation
386  * of that operator. It will not normally throw unless a custom
387  * allocator is used which throws on move assignment, or the
388  * destructor of a contained item throws.
389  * @param rhs The assignor/movant.
390  * @return The AsyncQueue object after move assignment.
391  *
392  * Since 2.0.8
393  */
395  Thread::Mutex::Lock lock{mutex};
396  q = std::move(rhs.q);
397  return *this;
398  }
399 
400 /**
401  * @exception std::bad_alloc The default constructor might throw
402  * std::bad_alloc if memory is exhausted and the system throws in that
403  * case.
404  * @exception Thread::MutexError The default constructor might throw
405  * Thread::MutexError if initialization of the contained mutex fails.
406  * (It is often not worth checking for this, as it means either memory
407  * is exhausted or pthread has run out of other resources to create
408  * new mutexes.)
409  */
410  AsyncQueue() = default;
411 
412 /**
413  * As regards thread safety, the move constructor does not synchronize
414  * with respect to the initializing rvalue. This is because
415  * temporaries are only visible and accessible in the thread carrying
416  * out the move operation and synchronization for them would represent
417  * pointless overhead. In a case where a user uses std::move to force
418  * a move from a named object, and that named object's lifetime is
419  * managed by (or the object is otherwise accessed by) a different
420  * thread than the one making the move, the user must carry out her
421  * own synchronization with respect to that different thread, both to
422  * ensure that a consistent view of the the named object is obtained
423  * and because that object will be mutated by the move.
424  * @param rhs The AsyncQueue object to be moved.
425  * @exception Thread::MutexError The move constructor might throw
426  * Thread::MutexError if initialization of the contained mutex fails.
427  * (It is often not worth checking for this, as it means either memory
428  * is exhausted or pthread has run out of other resources to create
429  * new mutexes.) It might also throw if the queue's container type's
430  * move constructor might throw, but it should not do that unless a
431  * custom allocator is in use.
432  * @note If this constructor throws Thread::MutexError, and a named
433  * object is moved using std::move, this constructor is not strongly
434  * exception safe (items in the moved queue will be lost). Fixing
435  * this efficiently requires changing the order of construction of
436  * data members of this class, which cannot be done until the next ABI
437  * break for this library as it would alter object layout. As noted
438  * above, in most cases the possibility of Thread::MutexError throwing
439  * can be ignored, but where that is not the case and strong exception
440  * safety is wanted, the user should either not employ std::move with
441  * named objects when invoking this class's constructors, or should
442  * construct an AsyncQueue object using the default constructor and
443  * then move assign to it.
444  *
445  * Since 2.0.8
446  */
447  AsyncQueue(AsyncQueue&& rhs): q(std::move(rhs.q)) {}
448 
449 /**
450  * The copy constructor is thread safe, as it locks the initializing
451  * object's mutex to obtain a consistent view of it.
452  * @param rhs The AsyncQueue object to be copied.
453  * @exception std::bad_alloc The copy constructor of the queue's
454  * container type, and so this constructor, might throw std::bad_alloc
455  * if memory is exhausted and the system throws in that case. It will
456  * also throw if the copy constructor of the queue's container type
457  * throws any other exceptions, including if any copy or move
458  * constructor or copy or move assignment operator of a contained item
459  * throws.
460  * @exception Thread::MutexError The copy constructor might throw
461  * Thread::MutexError if initialization of the contained mutex fails.
462  * (It is often not worth checking for this, as it means either memory
463  * is exhausted or pthread has run out of other resources to create
464  * new mutexes.)
465  *
466  * Since 2.0.8
467  */
468  // we use the comma operator here to lock the mutex and call the
469  // copy constructor: the lock will be retained until the end of the
470  // full expression in which it is lexically situated, namely until
471  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
472  AsyncQueue(const AsyncQueue& rhs): q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
473 
474 /**
475  * The destructor does not throw unless the destructor of a contained
476  * item throws. It is thread safe (any thread may delete the
477  * AsyncQueue object).
478  */
480  // lock and unlock the mutex in the destructor so that we have an
481  // acquire operation to ensure that when the std::queue object is
482  // destroyed memory is synchronised, so any thread may destroy the
483  // AsyncQueue object
484  Thread::Mutex::Lock lock{mutex};
485  }
486 
487 /* Only has effect if --with-glib-memory-slices-compat or
488  * --with-glib-memory-slices-no-compat option picked */
490 };
491 
492 /**
493  * @class AsyncQueueDispatch async_queue.h c++-gtk-utils/async_queue.h
494  * @brief A thread-safe asynchronous queue with a blocking pop()
495  * method.
496  * @sa AsyncQueue AsyncResult
497  *
498  * AsyncQueueDispatch is similar to the AsyncQueue class, except that
499  * it has a blocking pop_dispatch() method, which allows it to be
500  * waited on by a dedicated event/message dispatching thread for
501  * incoming work (represented by the data pushed onto the queue). In
502  * the same way, it can be used to implement thread pools, by having
503  * threads in the pool waiting on the queue. The AsyncResult class
504  * can be useful for passing results between threads in conjunction
505  * with AsyncQueueDispatch (the documentation on AsyncResult gives an
506  * example).
507  *
508  * By default the queue uses a std::list object as its container
509  * because in the kind of use mentioned above it is unlikely to hold
510  * many objects but it can be changed to, say, a std::deque object by
511  * specifying it as the second template parameter.
512  *
513  * If the library is installed using the
514  * --with-glib-memory-slices-compat or
515  * --with-glib-memory-slices-no-compat configuration options, any
516  * AsyncQueueDispatch objects constructed on free store will be
517  * constructed in glib memory slices. This does not affect the queue
518  * container itself: to change the allocator of the C++ container, a
519  * custom allocator type can be provided when the AsyncQueueDispatch
520  * object is instantiated offering the standard allocator interface.
521  * If glib memory slices are not used or no AsyncQueueDispatch objects
522  * are constructed on free store, it is not necessary to call
523  * g_thread_init() before manipulating or using an AsyncQueueDispatch
524  * object in multiple threads, but prior to glib version 2.32 glib
525  * itself (and thus glib memory slices) are not thread safe unless
526  * that function has been called.
527  */
528 
529 template <class T, class Container = std::list<T> > class AsyncQueueDispatch {
530 public:
531  typedef typename Container::value_type value_type;
532  typedef typename Container::size_type size_type;
533  typedef Container container_type;
534 private:
535 // TODO: put 'q' after 'mutex' and 'cond' at the next ABI break, so
536 // move construction is strongly exception safe
537  std::queue<T, Container> q;
538  mutable Thread::Mutex mutex;
539  Thread::Cond cond;
540 
541 // this won't throw: it is for the user to ensure the arguments do not
542 // refer to the same mutex object
543  void lock2(Thread::Mutex& m1, Thread::Mutex& m2) {
544  m1.lock();
545  for(;;) {
546  if (!m2.trylock()) {
547  return;
548  }
549  m1.unlock();
550  // spin nicely
551 #ifdef CGU_USE_SCHED_YIELD
552  sched_yield();
553 #else
554  usleep(10);
555 #endif
556  m1.lock();
557  }
558  }
559 public:
560 /**
561  * Pushes an item onto the queue. This method has strong exception
562  * safety if the container is a std::list or std::deque container (the
563  * default is std::list), except that if std::deque is used as the
564  * container and the copy constructor, move constructor, assignment
565  * operator or move assignment operator of the queue item throws, it
566  * only gives the basic exception guarantee (and the basic guarantee
567  * is not given by std::deque if the queue item's move constructor
568  * throws and it uses a non-default allocator which does not provide
569  * for it to be CopyInsertable). It is thread safe.
570  * @param obj The item to be pushed onto the queue.
571  * @exception std::bad_alloc The method might throw std::bad_alloc if
572  * memory is exhausted and the system throws in that case. It might
573  * also throw if the copy constructor, move constructor, assignment
574  * operator or move assignment operator of the queue item might throw.
575  */
576  void push(const value_type& obj) {
577  Thread::Mutex::Lock lock{mutex};
578  q.push(obj);
579  cond.signal();
580  }
581 
582 /**
583  * Pushes an item onto the queue. This method has strong exception
584  * safety if the container is a std::list or std::deque container (the
585  * default is std::list), except that if std::deque is used as the
586  * container and the copy constructor, move constructor, assignment
587  * operator or move assignment operator of the queue item throws, it
588  * only gives the basic exception guarantee (and the basic guarantee
589  * is not given by std::deque if the queue item's move constructor
590  * throws and it uses a non-default allocator which does not provide
591  * for it to be CopyInsertable). It is thread safe.
592  * @param obj The item to be pushed onto the queue.
593  * @exception std::bad_alloc The method might throw std::bad_alloc if
594  * memory is exhausted and the system throws in that case. It might
595  * also throw if the copy constructor, move constructor, assignment
596  * operator or move assignment operator of the queue item might throw.
597  *
598  * Since 2.0.0-rc5
599  */
600  void push(value_type&& obj) {
601  Thread::Mutex::Lock lock{mutex};
602  q.push(std::move(obj));
603  cond.signal();
604  }
605 
606 /**
607  * Pushes an item onto the queue by constructing it in place: that is,
608  * by passing to this method the item's constructor's arguments,
609  * rather than the item itself. This method has strong exception
610  * safety if the container is a std::list or std::deque container (the
611  * default is std::list). (Technically, for a std::deque container,
612  * emplace() only offers the same exception guarantees as does push(),
613  * namely only the basic guarantee where a copy or move of the queue
614  * item throws during the call, but the purpose of emplace is to
615  * construct in place and any reasonable implementation will not copy
616  * or move the queue item.) It is thread safe.
617  * @param args The constructor arguments for the item to be pushed
618  * onto the queue.
619  * @exception std::bad_alloc The method might throw std::bad_alloc if
620  * memory is exhausted and the system throws in that case. It might
621  * also throw if the item's constructor (including any of its
622  * constructor arguments) might throw when constructing the item.
623  * @note The constructor of the item pushed onto the queue must not
624  * access any of the methods of the same queue object, or a deadlock
625  * might occur.
626  *
627  * Since 2.0.0-rc5
628  */
629  template<class... Args>
630  void emplace(Args&&... args) {
631  Thread::Mutex::Lock lock{mutex};
632  q.emplace(std::forward<Args>(args)...);
633  cond.signal();
634  }
635 
636 /**
637  * Pops an item from the queue. This method has strong exception
638  * safety if the container is a std::deque or std::list container (the
639  * default is std::list), provided the destructor of a contained item
640  * does not throw. It is thread safe.
641  * @param obj A value type reference to which the item at the front of
642  * the queue will be assigned.
643  * @exception AsyncQueuePopError If the queue is empty when a pop is
644  * attempted, this method will throw AsyncQueuePopError. It might
645  * also throw if the assignment operator of the queue item might
646  * throw. In order to complete pop() operations atomically under a
647  * single lock and to retain strong exception safety, the object into
648  * which the pop()ed data is to be placed is passed as an argument by
649  * reference (this avoids a copy from a temporary object after the
650  * data has been extracted from the queue, which would occur if the
651  * item extracted were returned by value). It might also throw if the
652  * destructor of the queue item might throw (but that should never
653  * happen), or if the empty() method of the container type throws
654  * (which would not happen on any sane implementation).
655  */
656  void pop(value_type& obj) {
657  Thread::Mutex::Lock lock{mutex};
658  if (q.empty()) throw AsyncQueuePopError();
659  obj = q.front();
660  q.pop();
661  }
662 
663 /**
664  * Pops an item from the queue. If the queue is empty, it will block
665  * until an item becomes available. If it blocks, the wait comprises
666  * a cancellation point. This method is cancellation safe if the
667  * stack unwinds on cancellation, as cancellation is blocked while the
668  * queue is being operated on after coming out of a wait. This method
669  * has strong exception safety if the container is a std::deque or
670  * std::list container (the default is std::list), provided the
671  * destructor of a contained item does not throw. It is thread safe.
672  * @param obj A value type reference to which the item at the front of
673  * the queue will be assigned. This method might throw if the
674  * assignment operator of the queue item might throw. In order to
675  * complete pop() operations atomically under a single lock and to
676  * retain strong exception safety, the object into which the pop()ed
677  * data is to be placed is passed as an argument by reference (this
678  * avoids a copy from a temporary object after the data has been
679  * extracted from the queue, which would occur if the item extracted
680  * were returned by value). It might also throw if the destructor of
681  * the queue item might throw (but that should never happen), or if
682  * the empty() method of the container type throws (which would not
683  * happen on any sane implementation).
684  */
686  Thread::Mutex::Lock lock{mutex};
687  while (q.empty()) cond.wait(mutex);
689  obj = q.front();
690  q.pop();
691  }
692 
693 /**
694  * Pops an item from the queue. If the queue is empty, it will block
695  * until an item becomes available or until the timeout expires. If
696  * it blocks, the wait comprises a cancellation point. This method is
697  * cancellation safe if the stack unwinds on cancellation, as
698  * cancellation is blocked while the queue is being operated on after
699  * coming out of a wait. This method has strong exception safety if
700  * the container is a std::deque or std::list container (the default
701  * is std::list), provided the destructor of a contained item does not
702  * throw. It is thread safe.
703  * @param obj A value type reference to which the item at the front of
704  * the queue will be assigned. This method might throw if the
705  * assignment operator of the queue item might throw. In order to
706  * complete pop() operations atomically under a single lock and to
707  * retain strong exception safety, the object into which the pop()ed
708  * data is to be placed is passed as an argument by reference (this
709  * avoids a copy from a temporary object after the data has been
710  * extracted from the queue, which would occur if the item extracted
711  * were returned by value). It might also throw if the destructor of
712  * the queue item might throw (but that should never happen), or if
713  * the empty() method of the container type throws (which would not
714  * happen on any sane implementation).
715  * @param millisec The timeout interval, in milliseconds.
716  * @return If the timeout expires without an item becoming available,
717  * the method will return true. If an item from the queue is
718  * extracted, it returns false.
719  */
720  bool pop_timed_dispatch(value_type& obj, unsigned int millisec) {
721  timespec ts;
722  Thread::Cond::get_abs_time(ts, millisec);
723  Thread::Mutex::Lock lock{mutex};
724  while (q.empty()) {
725  if (cond.timed_wait(mutex, ts)) return true;
726  }
728  obj = q.front();
729  q.pop();
730  return false;
731  }
732 
733 /**
734  * Discards the item at the front of the queue. This method has
735  * strong exception safety if the container is a std::deque or
736  * std::list container (the default is std::list), provided the
737  * destructor of a contained item does not throw. It is thread safe.
738  * @exception AsyncQueuePopError If the queue is empty when a pop is
739  * attempted, this method will throw AsyncQueuePopError. It might
740  * also throw if the destructor of the queue item might throw (but
741  * that should never happen), or if the empty() method of the
742  * container type throws (which would not happen on any sane
743  * implementation).
744  */
745  void pop() {
746  Thread::Mutex::Lock lock{mutex};
747  if (q.empty()) throw AsyncQueuePopError();
748  q.pop();
749  }
750 
751 /**
752  * @return Whether the queue is empty. It will not throw assuming
753  * that the empty() method of the container type does not throw, as it
754  * will not on any sane implementation.
755  * @note This method is thread safe, but the return value may not be
756  * valid if another thread has pushed to or popped from the queue
757  * before the value returned by the method is acted on. It is
758  * provided as a utility, but may not be meaningful, depending on the
759  * intended usage.
760  */
761  bool empty() const {
762  Thread::Mutex::Lock lock{mutex};
763  return q.empty();
764  }
765 
766 /**
767  * @return The number of items currently in the queue. It will not
768  * throw assuming that the size() method of the container type does
769  * not throw, as it will not on any sane implementation.
770  * @note This method is thread safe, but the return value may not be
771  * valid if another thread has pushed to or popped from the queue
772  * before the value returned by the method is acted on. It is
773  * provided as a utility, but may not be meaningful, depending on the
774  * intended usage.
775  *
776  * Since 2.0.8
777  */
778  size_type size() const {
779  Thread::Mutex::Lock lock{mutex};
780  return q.size();
781  }
782 
783 /**
784  * Swaps the contents of 'this' and 'other'. It will not throw
785  * assuming that the swap method of the container type does not throw
786  * (which the C++11 standard requires not to happen with the standard
787  * sequence containers). It is thread safe and the swap is
788  * thread-wise atomic. A non-class function
789  * Cgu::swap(Cgu::AsyncQueue&, Cgu::AsyncQueue&) method is also
790  * provided which will call this method.
791  * @param other The object to be swapped with this one.
792  * @note An object swapped does not, by virtue of the swap, inherit
793  * any threads waiting on the other one. However if threads were
794  * waiting on a swapped object prior to the swap, and it acquires
795  * items by virtue of the swap, the waiting threads will unblock and
796  * extract those items.
797  *
798  * Since 2.0.8
799  */
800  void swap(AsyncQueueDispatch& other) {
801  if (this != &other) {
802  lock2(mutex, other.mutex); // doesn't throw
804  Thread::Mutex::Lock l2{other.mutex, Thread::locked};
805  q.swap(other.q);
806  if (!q.empty()) cond.broadcast();
807  if (!other.q.empty()) other.cond.broadcast();
808  }
809  }
810 
811 /**
812  * The assignment operator is strongly exception safe with the
813  * standard sequence containers (it uses copy and swap). It is also
814  * thread safe, as it safely locks both the assignor's and assignee's
815  * mutex to provide a thread-wise atomic assignment.
816  * @param rhs The assignor.
817  * @return The AsyncQueueDispatch object after assignment.
818  * @exception std::bad_alloc The copy constructor of the queue's
819  * container type, and so this assignment operator, might throw
820  * std::bad_alloc if memory is exhausted and the system throws in that
821  * case. This assignment operator will also throw if the copy
822  * constructor of the queue's container type throws any other
823  * exceptions, including if any copy or move constructor or copy or
824  * move assignment operator of a contained item throws.
825  * @exception Thread::MutexError The assignment operator might throw
826  * Thread::MutexError if initialization of a transitional object's
827  * contained mutex fails. (It is often not worth checking for this,
828  * as it means either memory is exhausted or pthread has run out of
829  * other resources to create new mutexes.)
830  * @exception Thread::CondError The assignment operator might throw
831  * this exception if initialisation of a transitional object's
832  * contained condition variable fails. (It is often not worth
833  * checking for this, as it means either memory is exhausted or
834  * pthread has run out of other resources to create new condition
835  * variables.)
836  * @note The assignee does not, by virtue of the assignment, inherit
837  * any threads waiting on the assignor. However, if prior to the
838  * assignment threads were waiting on the assignee and the assignee
839  * acquires items from the assignor as a result of the assignment, the
840  * waiting threads will unblock and extract those items.
841  *
842  * Since 2.0.8
843  */
845  if (this != &rhs) {
846  lock2(mutex, rhs.mutex); // doesn't throw
848  Thread::Mutex::Lock l2{rhs.mutex, Thread::locked};
849  std::queue<T, Container> temp{rhs.q};
850  q.swap(temp);
851  if (!q.empty()) cond.broadcast();
852  }
853  return *this;
854  }
855 
856 /**
857  * This move assignment operator is thread safe as regards the
858  * assignee (the object moved to), but no synchronization is carried
859  * out with respect to the rvalue assignor/movant. This is because
860  * temporaries are only visible and accessible in the thread carrying
861  * out the move operation and synchronization for them would represent
862  * pointless overhead. In a case where the user uses std::move to
863  * force a move from a named object, and that named object's lifetime
864  * is managed by (or the object is otherwise accessed by) a different
865  * thread than the one making the move, the user must carry out her
866  * own synchronization with respect to that different thread, both to
867  * ensure that a consistent view of the the named object is obtained
868  * and because that object will be mutated by the move. This method
869  * invokes std::queue's move assignment operator, and therefore has
870  * the same exception safety as the standard library's implementation
871  * of that operator. It will not normally throw unless a custom
872  * allocator is used which throws on move assignment, or the
873  * destructor of a contained item throws.
874  * @param rhs The assignor/movant.
875  * @return The AsyncQueueDispatch object after move assignment.
876  * @note The assignee does not, by virtue of the move, inherit any
877  * threads waiting on the assignor/movant. However, if prior to the
878  * move threads were waiting on the assignee and the assignee acquires
879  * items from the assignor/movant as a result of the move, from
880  * version 2.0.9 the waiting threads will unblock and extract those
881  * items (such unblocking on move assignment did not happen with
882  * version 2.0.8, which was a bug).
883  *
884  * Since 2.0.8
885  */
887  Thread::Mutex::Lock lock{mutex};
888  q = std::move(rhs.q);
889  if (!q.empty()) cond.broadcast();
890  return *this;
891  }
892 
893 /**
894  * @exception std::bad_alloc The default constructor might throw this
895  * exception if memory is exhausted and the system throws in that
896  * case.
897  * @exception Thread::MutexError The default constructor might throw
898  * this exception if initialisation of the contained mutex fails. (It
899  * is often not worth checking for this, as it means either memory is
900  * exhausted or pthread has run out of other resources to create new
901  * mutexes.)
902  * @exception Thread::CondError The default constructor might throw
903  * this exception if initialisation of the contained condition
904  * variable fails. (It is often not worth checking for this, as it
905  * means either memory is exhausted or pthread has run out of other
906  * resources to create new condition variables.)
907  */
908  AsyncQueueDispatch() = default;
909 
910 /**
911  * As regards thread safety, the move constructor does not synchronize
912  * with respect to the initializing rvalue. This is because
913  * temporaries are only visible and accessible in the thread carrying
914  * out the move operation and synchronization for them would represent
915  * pointless overhead. In a case where a user uses std::move to force
916  * a move from a named object, and that named object's lifetime is
917  * managed by (or the object is otherwise accessed by) a different
918  * thread than the one making the move, the user must carry out her
919  * own synchronization with respect to that different thread, both to
920  * ensure that a consistent view of the the named object is obtained
921  * and because that object will be mutated by the move.
922  * @param rhs The AsyncQueueDispatch object to be moved.
923  * @exception Thread::MutexError The move constructor might throw
924  * Thread::MutexError if initialization of the contained mutex fails.
925  * (It is often not worth checking for this, as it means either memory
926  * is exhausted or pthread has run out of other resources to create
927  * new mutexes.) It might also throw if the queue's container type's
928  * move constructor might throw, but it should not do that unless a
929  * custom allocator is in use.
930  * @exception Thread::CondError The move constructor might throw this
931  * exception if initialisation of the contained condition variable
932  * fails. (It is often not worth checking for this, as it means
933  * either memory is exhausted or pthread has run out of other
934  * resources to create new condition variables.) It might also throw
935  * if the queue's container type's move constructor might throw, but
936  * it should not do that unless a custom allocator is in use.
937  * @note If this constructor throws Thread::MutexError or
938  * Thread::CondError, and a named object is moved using std::move,
939  * this constructor is not strongly exception safe (items in the moved
940  * queue will be lost). Fixing this efficiently requires changing the
941  * order of construction of data members of this class, which cannot
942  * be done until the next ABI break for this library as it would alter
943  * object layout. As noted above, in most cases the possibility of
944  * Thread::MutexError or Thread::CondError throwing can be ignored,
945  * but where that is not the case and strong exception safety is
946  * wanted, the user should either not employ std::move with named
947  * objects when invoking this class's constructors, or should
948  * construct an AsyncQueueDispatch object using the default
949  * constructor and then move assign to it.
950  *
951  * Since 2.0.8
952  */
953  AsyncQueueDispatch(AsyncQueueDispatch&& rhs): q(std::move(rhs.q)) {}
954 
955 /**
956  * The copy constructor is thread safe, as it locks the initializing
957  * object's mutex to obtain a consistent view of it.
958  * @param rhs The AsyncQueueDispatch object to be copied.
959  * @exception std::bad_alloc The copy constructor of the queue's
960  * container type, and so this constructor, might throw std::bad_alloc
961  * if memory is exhausted and the system throws in that case. It will
962  * also throw if the copy constructor of the queue's container type
963  * throws any other exceptions, including if any copy or move
964  * constructor or copy or move assignment operator of a contained item
965  * throws.
966  * @exception Thread::MutexError The copy constructor might throw
967  * Thread::MutexError if initialization of the contained mutex fails.
968  * (It is often not worth checking for this, as it means either memory
969  * is exhausted or pthread has run out of other resources to create
970  * new mutexes.)
971  * @exception Thread::CondError The copy constructor might throw this
972  * exception if initialisation of the contained condition variable
973  * fails. (It is often not worth checking for this, as it means
974  * either memory is exhausted or pthread has run out of other
975  * resources to create new condition variables.)
976  *
977  * Since 2.0.8
978  */
979  // we use the comma operator here to lock the mutex and call the
980  // copy constructor: the lock will be retained until the end of the
981  // full expression in which it is lexically situated, namely until
982  // the end of q's constructor - see C++11 1.9/10 and 12.2/3
984  q((Thread::Mutex::Lock(rhs.mutex), rhs.q)) {}
985 
986 /**
987  * The destructor does not throw unless the destructor of a contained
988  * item throws. It is thread safe (any thread may delete the
989  * AsyncQueueDispatch object). Destroying an AsyncQueueDispatch
990  * object on which another thread is currently blocked results in
991  * undefined behavior.
992  */
994  // lock and unlock the mutex in the destructor so that we have an
995  // acquire operation to ensure that when the std::queue object is
996  // destroyed memory is synchronised, so any thread may destroy the
997  // AsyncQueueDispatch object
998  Thread::Mutex::Lock lock{mutex};
999  }
1000 
1001 /* Only has effect if --with-glib-memory-slices-compat or
1002  * --with-glib-memory-slices-no-compat option picked */
1004 };
1005 
1006 /**
1007  * Swaps the contents of two AsyncQueue objects. It will not throw
1008  * assuming that the swap method of the container type does not throw
1009  * (which the C++11 standard requires not to happen with the standard
1010  * sequence containers). It is thread safe and the swap is
1011  * thread-wise atomic.
1012  * @param q1 An object to be swapped with the other.
1013  * @param q2 An object to be swapped with the other.
1014  * @note Calling std::swap on AsyncQueue objects is thread safe but
1015  * does not provide a thread-wise atomic swap (the swapped objects may
1016  * not be mirror images if during the execution of std::swap's default
1017  * algorithm one of them has been modified), although in many cases
1018  * that doesn't matter. If swap() is called without a namespace
1019  * qualifier, argument dependent look-up will pick this one correctly.
1020  *
1021  * Since 2.0.8
1022  */
1023 template <class T, class Container>
1026  q1.swap(q2);
1027 }
1028 
1029 /**
1030  * Swaps the contents of two AsyncQueue objects. It will not throw
1031  * assuming that the swap method of the container type does not throw
1032  * (which the C++11 standard requires not to happen with the standard
1033  * sequence containers). It is thread safe and the swap is
1034  * thread-wise atomic.
1035  * @param q1 An object to be swapped with the other.
1036  * @param q2 An object to be swapped with the other.
1037  * @note 1. An object swapped does not, by virtue of the swap, inherit
1038  * any threads waiting on the other one. However if threads were
1039  * waiting on a swapped object prior to the swap, and it acquires
1040  * items by virtue of the swap, the waiting threads will unblock and
1041  * extract those items.
1042  * @note 2. Calling std::swap on AsyncQueueDispatch objects is thread
1043  * safe but does not provide a thread-wise atomic swap (the swapped
1044  * objects may not be mirror images if during the execution of
1045  * std::swap's default algorithm one of them has been modified),
1046  * although in many cases that doesn't matter. If swap() is called
1047  * without a namespace qualifier, argument dependent look-up will pick
1048  * this one correctly.
1049  *
1050  * Since 2.0.8
1051  */
1052 template <class T, class Container>
1055  q1.swap(q2);
1056 }
1057 
1058 } // namespace Cgu
1059 
1060 #endif