Reducing design complexity using boost :: asio

The code included in this question shows a chained set of callbacks using boost :: asio. In this case, the code is very clear because the chain length is short.

In real-world applications, the callback chain is often much longer and must include callbacks for timeouts and code to handle errors or poorly formatted messages. This quickly becomes very complex, similar to 1960s design with too many gotos.

Some of the complexity can be addressed by layering the code, but since the design is asynchronous, some sort of callback chaining is inevitable somewhere.

Or that? Are there ways to reduce the complexity of asynchronous design? (Obviously using streams will help in some cases, but I'm looking for a single threaded solution.)

+3


source to share


1 answer


The typical response to this would be to use co-routines.

Boost Asio has two flavors:

  • Stackless Coroutines

    They are fully compatible and do not allow stack switching. Instead, they use ingenious cracking with operators switch

    and several macros ( yield

    , reenter

    , fork

    ).

    The downside to this is that the coroutines in this project are functors and the functor has to be copied. It offers options with participation shared_ptr

    just to make it convenient.

    Shared pointers have their own overhead, which may or may not affect your application.

  • Stacks of Coroutines

    They are still interoperable, but they use the Boost Context (via the Boost Coroutine library) to actually switch stacks. This removes quite a lot of the previously mentioned red ribbon, but introduces other tradeoffs:

    • this can lead to slight inefficiencies; compared to "flat" async in a single thread, it introduces context switching, which ironically makes it look like multithreading, albeit without threads
    • it introduces a dependency on non-header libraries. Boost Context and Boost Coroutines, which are not supported on all target platforms supported by the Boost libraries.

    Stacked coroutines usually start by using boost::asio::spawn



I like to think of Stackful Coroutines as a collaborative multitasking abstraction that can run inside a fully bootable ecosystem shipped by the OS.

Boost Asio contains samples of both Coroutines styles

+3


source







All Articles