c++-gtk-utils
|
A thread-safe "channel" class for inter-thread communication. More...
#include <c++-gtk-utils/async_channel.h>
Public Types | |
typedef T | value_type |
typedef std::size_t | size_type |
Public Member Functions | |
AsyncChannel (const AsyncChannel &)=delete | |
AsyncChannel & | operator= (const AsyncChannel &)=delete |
void | close () noexcept |
bool | push (const value_type &obj) |
bool | push (value_type &&obj) |
template<class... Args> | |
bool | emplace (Args &&... args) |
bool | pop (value_type &obj) |
bool | move_pop (value_type &obj) |
AsyncChannel () | |
~AsyncChannel () | |
A thread-safe "channel" class for inter-thread communication.
AsyncChannel is similar to the AsyncQueueDispatch class, in that it provides a means of sending data between threads. Producer threads push data onto the queue and consumer threads pop them off in a thread safe way, and if there are no data in the channel any consumer thread will block until a producer thread pushes an item onto it. However, unlike the AsyncQueueDispatch class, it has a fixed maximum size as part of its type, which may be any size greater than 0, and if the number of data items still in the channel is such as to make the channel full, then producer threads will block on the channel until a consumer thread pops an item from it.
It therefore provides for back pressure on producer threads which will automatically prevent the channel being overwhelmed by producer threads pushing more items onto the queue than consumer threads have the capacity to take off it.
AsyncChannel is useful where this feature is important, and an AsyncChannel object can be used with any number of producer threads and consumer threads. However, under heavy contention with complex data item types AsyncQueueDispatch objects will usually be faster. Under lower contention and with simpler data types (or where temporary objects with non-complex move constructors are pushed), an AsyncChannel object may be faster as it can benefit from its fixed buffer size (the AsyncChannel implementation uses a circular buffer with in-buffer construction of data items).
AsyncChannel objects are instantiated with firstly a template type 'T' and secondly a template integer value 'n'. 'T' is the type of the data items to be placed on the queue. 'n' is the size of the channel, which as mentioned may be any size greater than 0.
This class is available from version 2.2.14.
typedef std::size_t Cgu::AsyncChannel< T, n >::size_type |
typedef T Cgu::AsyncChannel< T, n >::value_type |
|
delete |
This class cannot be copied. The copy constructor is deleted.
|
inline |
AsyncChannel objects are instantiated with firstly a template type 'T' and secondly a template integer value 'n'. 'T' is the type of the data items to be placed on the queue. 'n' is the size of the channel, which must be greater than 0. However, a circular buffer for that size will be allocated at construction time by this default constructor, so the given size should not be unnecessarily large. Where a large AsyncChannel object would be required, consider using AsyncQueueDispatch instead, which sizes itself dynamically.
std::bad_alloc | The default constructor might throw this exception if memory is exhausted and the system throws in that case. |
Thread::MutexError | The default constructor might throw this exception if initialisation of the contained mutex fails. (It is often not worth checking for this, as it means either memory is exhausted or pthread has run out of other resources to create new mutexes.) |
Thread::CondError | The default constructor might throw this exception if initialisation of the contained condition variable fails. (It is often not worth checking for this, as it means either memory is exhausted or pthread has run out of other resources to create new condition variables.) |
Since 2.0.31 and 2.2.14
|
inline |
The destructor does not throw unless the destructor of a data item in the channel throws. It is thread safe (any thread may delete the AsyncChannel object).
It is not an error for a thread to destroy the AsyncChannel object and so invoke this destructor while another thread is blocking on it: instead the destructor will release any blocking threads. The destructor will not return until all threads (if any) blocking on the AsyncChannel object have been released.
Since 2.0.31 and 2.2.14
|
inlinenoexcept |
Closes the channel. This means that (i) any threads blocking on a full channel with a call to push() or emplace() will unblock with a false return value, and any calls to those methods after the closure will return immediately with a false return value, (ii) any threads blocking on an empty channel with calls to pop() or move_pop() will unblock with a false return value, (iii) any data items remaining in the channel which were pushed to the channel prior to the closure of the channel can be popped after that closure by further calls to pop() or move_pop(), which will return normally with a true return value, and (iv) after any such remaining data items have been removed, any subsequent calls to pop() or move_pop() will return with a false return value.
If called more than once, this method will do nothing.
This method will not throw. It is thread safe - any thread may call it.
One of the main purposes of this method is to enable a producer thread to inform a consumer thread that nothing more will be put in the channel by it for the consumer: for such cases, as mentioned once everything pushed to the channel prior to its closure has been extracted from the channel by pop() or move_pop() calls, any further pop() or move_pop() calls will return false. At that point the consumer thread can abandon and destroy the AsyncChannel object.
Since 2.0.31 and 2.2.14
|
inline |
Pushes an item onto the channel by constructing it in place from the given arguments. This method will only throw if the constructor of the emplaced item throws, and has strong exception safety in such a case. It is thread safe.
If the number of items already in the channel is equal to the size of the channel, then this method blocks until either room becomes available for the item by virtue of another thread calling the pop() or move_pop() methods, or another thread calls the close() method. If it blocks, the wait comprises a cancellation point. This method is cancellation safe if the stack unwinds on cancellation, as cancellation is blocked while the channel is being operated on after coming out of a wait.
args | The constructor arguments for the item to be pushed onto the channel. |
Since 2.0.31 and 2.2.14
|
inline |
Pops an item from the channel using the item type's move assignment operator if it has one, or if not its copy assignment operator (this method is identical to the pop() method if that type has no move assignment operator). This method will only throw if that operator throws or the contained item's destructor throws. It has strong exception safety, provided the destructor of the contained item does not throw and the move assignment operator of the contained item has strong exception safety. Use this method in preference to the pop() method if it is known that the contained items' move assignment operator does not throw or is strongly exception safe, or if the use case does not require strong exception safety. This method must be used in place of the pop() method if the contained item has a move assignment operator but no copy assignment operator (such as a std::unique_ptr object). It is thread safe.
If the channel is empty, then this method blocks until either an item becomes available by virtue of another thread calling the emplace() or push() methods, or another thread calls the close() method. If it blocks, the wait comprises a cancellation point. This method is cancellation safe if the stack unwinds on cancellation, as cancellation is blocked while the channel is being operated on after coming out of a wait.
obj | A value type reference to which the item at the front of the channel will be move assigned. |
Since 2.0.31 and 2.2.14
|
delete |
This class cannot be copied. The assignment operator is deleted.
|
inline |
Pops an item from the channel using the item type's copy assignment operator. This method will only throw if that operator throws or the contained item's destructor throws. It has strong exception safety, provided the destructor of the contained item does not throw. See also the move_pop() method. It is thread safe.
If the channel is empty, then this method blocks until either an item becomes available by virtue of another thread calling the emplace() or push() methods, or another thread calls the close() method. If it blocks, the wait comprises a cancellation point. This method is cancellation safe if the stack unwinds on cancellation, as cancellation is blocked while the channel is being operated on after coming out of a wait.
obj | A value type reference to which the item at the front of the channel will be copy assigned. |
Since 2.0.31 and 2.2.14
|
inline |
Pushes an item onto the channel. This method will only throw if the copy constructor of the pushed item throws, and has strong exception safety in such a case. It is thread safe.
If the number of items already in the channel is equal to the size of the channel, then this method blocks until either room becomes available for the item by virtue of another thread calling the pop() or move_pop() methods, or another thread calls the close() method. If it blocks, the wait comprises a cancellation point. This method is cancellation safe if the stack unwinds on cancellation, as cancellation is blocked while the channel is being operated on after coming out of a wait.
obj | The item to be pushed onto the channel. |
Since 2.0.31 and 2.2.14
|
inline |
Pushes an item onto the channel. This method will only throw if the move constructor, or if none the copy constructor, of the pushed item throws, and has strong exception safety in such a case. It is thread safe.
If the number of items already in the channel is equal to the size of the channel, then this method blocks until either room becomes available for the item by virtue of another thread calling the pop() or move_pop() methods, or another thread calls the close() method. If it blocks, the wait comprises a cancellation point. This method is cancellation safe if the stack unwinds on cancellation, as cancellation is blocked while the channel is being operated on after coming out of a wait.
obj | The item to be pushed onto the channel. |
Since 2.0.31 and 2.2.14