Consider an echo server implemented using Boost.asio. Read events from connected clients result in blocks of data being placed on to an arrival event queue. A pool of thread
A strand is an execution context which executes handlers within a critical section, on a correct thread.
That critical section is implemented (more or less) with a mutex.
It's a little cleverer than that because if a dispatcher detects that a thread is already in the strand, it appends the handler to a queue of handlers to be executed before the critical section has been left, but after the current handler has completed.
thus in this case the new handler is 'sort of' posted to the currently executing thread.
There are some guarantees in ordering.
strand::post/dispatch(x);
strand::post/dispatch(y);
will always result in x happening before y.
but if x dispatches a handler z during its execution, then the execution order will be:
x, z, y
note that the idiomatic way to handle io completion handlers with strands is not to post work to a strand in the completion handler, but to wrap the completion handler in the strand, and do the work there.
asio contains code to detect this and will do the right thing, ensuring correct ordering and eliding un-necessary intermediate posts.
e.g.:
async_read(sock, mystrand.wrap([](const auto& ec, auto transferred)
{
// this code happens in the correct strand, in the correct order.
});