c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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