Does boost::asio::io_service preserve the order of handlers?
Asked Answered
H

3

13

Does boost::asio::io_service guarantee that handlers are called in the same order that they are given via post()? I can't find anything saying this in the documentation. Assume that calls to io_service::post are serialized.

Harry answered 22/6, 2011 at 15:51 Comment(1)
If you are using Boost.Asio then you are definitely too modest, because that's a smart approach to solving a hard problem.Headstream
U
9

The current implementation does execute things in the sequence you post them, but ordering is only guaranteed for handlers that are explicitly post()ed through a strand.

Uncertainty answered 22/6, 2011 at 16:10 Comment(1)
If there is just 1 worker thread, and ordering is required, do we still require a strand, or strand not needed when 1 worker thread is there?Duwalt
H
10

afaik if you want guaranteed ordering of post handler execution you have to use strand as described in the docs.

Headstream answered 22/6, 2011 at 16:7 Comment(1)
If there is just 1 worker thread, and ordering is required, do we still require a strand, or strand not needed when 1 worker thread is there?Duwalt
U
9

The current implementation does execute things in the sequence you post them, but ordering is only guaranteed for handlers that are explicitly post()ed through a strand.

Uncertainty answered 22/6, 2011 at 16:10 Comment(1)
If there is just 1 worker thread, and ordering is required, do we still require a strand, or strand not needed when 1 worker thread is there?Duwalt
B
0

~~It seemed for strand not to preserve handler execution by the order that you post (unlike LinkedHashMap, when you iterate, you iterate the elements by the order that you've inserted them). I think it just ensures those handlers won't be invoked at the same time.~~

See also How strands guarantee correct execution of pending events in boost.asio

strand provides a guarantee for non-concurrency and the invocation order of handlers

In some case, there is no guarantee correct execution if using io_context::strand::wrap (deprecated) or bind_executor in async_op_1(..., s.wrap(a));. When the async operation completes, the wrapped handler will call s.dispatch(a), but the completion time is uncertain.

The io_context::strand class provides the ability to post and dispatch handlers with the guarantee that none of those handlers will execute concurrently.

See also

strand provides both the guarantee of not executing completion handlers concurrently and defines the order of handler invocation. In short, completion handlers posted into a strand are executed in the same order in which they are posted.

Therefore:

strand_.post(&task1);
strand_.post(&task2);
strand_.post(&task3);

Guarantees order of handler invocation is task1 -> task2 -> task3. However, wrapped completion handlers for asynchronous operations are not guaranteed, as the order in which asynchronous operations are performed is unspecified. For example, the following does not provide the same guarantee:

async_read(socket1, ..., strand_.wrap(&task1));
async_read(socket2, ..., strand_.wrap(&task2));
async_read(socket3, ..., strand_.wrap(&task3));

If completion handlers must be invoked in a specified order for asynchronous operations, then either:

Queue completion handlers and manage the order manually. Serialize all asynchronous operations. For example, async_op_1's completion handler task1 initiates async_op_2 with a completion handler of task2.

Here is the relevant excerpt from io_service::strand's order of handler invocation documentation:

Brucine answered 1/12, 2021 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.