Asynchronous I/O

The C++ API uses Boost.Asio for asynchronous operations. There is a spead2::thread_pool class (essentially the same as the Python spead2.ThreadPool class). However, it is not required to use this, and you may for example run everything in one thread to avoid multi-threading issues.

class thread_pool

Combination of a boost::asio::io_service with a set of threads to handle the callbacks.

The threads are created by the constructor and shut down and joined in the destructor.

Subclassed by spead2::thread_pool_wrapper

Public Functions

thread_pool(int num_threads, const std::vector<int> &affinity)

Construct with explicit core affinity for the threads.

The affinity list can be shorter or longer than num_threads. Threads are allocated in round-robin fashion to cores. Failures to set affinity are logged but do not cause an exception.

inline boost::asio::io_service &get_io_service()

Retrieve the embedded io_service.

void stop()

Shut down the thread pool.

Public Static Functions

static void set_affinity(int core)

Set CPU affinity of current thread.

Classes that perform asynchronous operations take a parameter of type spead2::io_service_ref. This can be (implicitly) initialised from either a boost::asio::io_service reference, a spead2::thread_pool reference, or a std::shared_ptr<spead2::thread_pool>. In the last case, the receiving class retains a copy of the shared pointer, providing convenient lifetime management of a thread pool.

class io_service_ref

A helper class that holds a reference to a boost::asio::io_service, and optionally a shared pointer to a thread_pool.

It is normally not explicitly constructed, but other classes that need an io_service take it as an argument and store it so that they can accept any of io_service, thread_pool or std::shared_ptr<thread_pool>, and in the last case they hold on to the reference.

Public Functions

io_service_ref(boost::asio::io_service&)

Construct from a reference to an io_service.

io_service_ref(thread_pool&)

Construct from a reference to a thread_pool.

template<typename T, typename SFINAE = std::enable_if_t<std::is_convertible_v<T*, thread_pool*>>>
io_service_ref(std::shared_ptr<T>)

Construct from a shared pointer to a thread_pool.

This is templated so that it will also accept a shared pointer to a subclass of thread_pool.

boost::asio::io_service &operator*() const

Return the referenced io_service.

boost::asio::io_service *operator->() const

Return a pointer to the referenced io_service.

std::shared_ptr<thread_pool> get_shared_thread_pool() const &

Return the shared pointer to the thread_pool, if constructed from one.

std::shared_ptr<thread_pool> &&get_shared_thread_pool() &&

Return the shared pointer to the thread_pool, if constructed from one.

This overload returns an rvalue reference, allowing the shared pointer to be moved out of a temporary.

A number of the APIs use callbacks. These follow the usual Boost.Asio guarantee that they will always be called from threads running boost::asio::io_service::run(). If using a thread_pool, this will be one of the threads managed by the pool. Additionally, callbacks for a specific stream are serialised, but there may be concurrent callbacks associated with different streams.