How-To share data with a concurrent queue

Working with threads often means distributing stuff from one thread to the next. And doing that also means taking into account that one thread might be slower than the other. Arguably, one of the main use cases of threads is to keep a user interface thread responsive, whilst working on some work packages in the background.

For this, this library includes :cpp:liberate::concurrency::concurrent_queue.

This is not entirely lock free – it uses user-space spin locks – but it does not require system primitives for serializing access to data and so is pretty much free of overhead unless there is contention.

The queue has an interface reminiscent of standard library containers, but it’s not quite the same. Data used in the queue is expected to be CopyConstructable.

Concurrent queue; push work
1#include <liberate/concurrency/concurrent_queue.h>
2
3using namespace liberate::concurrency;
4
5concurrent_queue<my_data_type> queue;
6
7// Push work into the queue
8my_data_type data{/* ... */};
9queue.push(data);

Pushing work in the form of data is simple, as you can see. You can also push a range of values from a container.

Concurrent queue; push more work
1std::vector<my_data_type> more_data;
2queue.push_range(more_data.begin(), more_data.end());

Retrieving data is a little different from how you might expect; it requires returning two values: a boolean indicating whether work was available, and if so, the value itself.

Concurrent queue; retrieve work
1auto [success, data] = queue.pop();
2if (success) {
3  // use data
4}