The queue can be accessed by multiple producers and consumers from multiple threads. When consumers get data from the queue it is removed the queue.
Concurrent::Queue<std::string> queue;
queue.push("Hello");
queue.push("World");
Data returned from the queue will be removed from the queue.
If the queue is empty, tryGet()
will return (a std::optional
) immediately.
auto val = queue.tryGet();
if (val){
std::cout << "My data is " << *val;
}
else{
std::cout << "The queue was empty";
}
If the queue is empty, waitGet()
will wait until a producer puts something in the queue
auto val = queue.waitGet(); // Execution will wait here if the queue is empty
std::cout << "My data is " << val;
This function needs to return 2 bits of information
- Whether it was successful
- Potentially the popped data
Option: The underlying container could be changed to std::deque
to allow iterator access.
Reason: The concurrentQueue should not return an iterator to the underlying container because then a user could break the encapsulation and bypass the thread safety to access queue elements.
Option: The function could return a nullptr
if the queue was empty and return a pointer to the data if it was possible.
Reason: This would result in memory allocation on the heap every time data is accessed.
Option: If data was available the function could return the data, and true
to signify the data is good.
Otherwise the return type would be default constructed and returned with a false
to signify the data is bad.
The bool should be the 2nd param to be consistent with the STL and for performance reasons.
Reason: This means only default constructable objects can be stored in the queue.
Option: Similar to the pair method except the data is returned via an out parameter. This puts the responsibility on the calling code to construct the object.
Reason: Results in extra code on the client side
Option: An exception could be thrown when trying to access an empty queue.
Reason: An empty queue isn't exceptional. Exceptions shouldn't be used for control flow.
Option: Return a std::optional
.
Reason: Calling code doesn't have to construct any out parameter objects.
Clean syntax to check if data is valid.
std::shared_mutex
allows for multiple readers (non-modifying) access to the queue at the same time. However that means the less efficient std::condition_variable_any
has to be used (rather than std::condition_variable
).
Under most circumstances there is no value in querying the state of the queue since there is no guarantee that the state will not be changed by another thread before you can make an action based off of the state. Therefore it is not worth making performance sacrifices for shared reading of the queue.