Boost asio strand and io_service running on several threads
asynchronous, boost-asio, c++, multithreading
Solution
In short, a `strand` guarantees sequential invocation of its own handlers, but makes no guarantee of concurrent execution of handlers from different strands. Thus, the answers to the points are:
- Yes. Sequential invocation is guaranteed.
- Yes. Concurrent execution could happen, but there is no guarantee.
- Yes to sequential invocation, but no to the the guarantee that concurrent execution will occur.
A `strand` maintains its own handler queue, and guarantees that only one of its handlers is in the `io_service`, resulting in handlers being synchronized before being placed into the `io_service`. Thus, all handlers posted or dispatched through a `strand` will be executed sequentially.
Concurrent execution of handlers posted or dispatched through different `strand`s can occur, it is just not guaranteed to occur. The documentation states:
The implementation makes no guarantee that handlers posted or dispatched through different strand objects will be invoked concurrently.
Therefore, if `Thread1` is executing a handler posted through `Strand_1`, Boost.Asio will not use that information to guarantee that a handler posted through `Strand_2` will be executed by `Thread2`; however, it is possible that `Thread2` is selected to execute the handler from `Strand_2` based on other implementation details, such as being the next available thread in the list of threads running the `io_service`.
For example, consider the case where 3 handlers `A`, `B`, and `C` are ready to run within the `io_service`:
- `A` was posted posted through `Strand_1`.
- `B` was not posted through a `strand`.
- `C` was posted through `Strand_2`.
If `Thread1` and `Thread2` are running the `io_service`, then one possible execution order is:
Thread1 | Thread2
----------------+----------------
start A() | start B()
`-- finish A() | |
start C() | `-- finish B()
`-- finish C() |
The illustrated execution order shows that that handlers (`A` and `C`) posted through different `strand`s (`Strand_1` and `Strand_2` respectively) are not guaranteed to be executed concurrently.
Problem
I am not sure about one detail related to strands. Suppose the following situation: two independent objects each one with his own strand. And each strand related to one common io_service. Each object use his strand for posting and wrapping async operations. If I have this (unique) io_service .run()'ing on several threads, I am not sure if the following will happen: All operations posted and async wrapped by one of the objects will be executed non concurrently. So all operations related to one of the objects will be executed serially (Posted operations will be executed in the same order than they were posted. Wrapped async operations will be executed in an unspecified order because they are asynchronous but still being executed serially). Two operations originated in different objects (and therefore posted or wrapped from different strand objects related to the same io_service) could be executed concurrently. In summary, each object will execute his posted and wrapped handlers serially but handlers posted and wrapped from different objects (strands) will execute concurrently. ``` +-----------------+ +-----------------+ | Obj1 | | Obj2 | | +-------------+ | | +-------------+ | | | Strand_1 | | | | Strand_2 | | | +-------------+ | | +-------------+ | +--------+--------+ +-------+---------+ | | +--------+ +-------+ | | +----+--+----+ | io_service | +------------+ | | +--------+-------+ | | Thread1 Thread_2 io_service.run() io_service.run() ``` Am I right? Thank you