Daniele Pallastrelli
Daniele Pallastrelli

Reputation: 2552

How to make C++ async programming more linear (coroutines?)

in C++14 I'd like to build a mechanism to use asynchronous APIs in a "sequential" way, using a single thread.

To be more explicit, I'd like to achive something like this:

// Transform AsyncOp1 into SyncOp1
// SyncOp1 returns after AsyncOp1 completes
// but yields execution to another script
void SyncOp1()
{
    AsyncOp1( [](){ // async op completion handler
        // TODO: yield control
    } );
    // TODO: control returns here after AsyncOp1 completed
}

... // similar code for SyncOp2, SyncOp3, SyncOp4,...

void Script1()
{
    SyncOp1(); 
    SyncOp2(); // SyncOp2 starts only after AsyncOp1 has completed
    ...
}

void Script2()
{
    SyncOp3(); 
    SyncOp4(); // SyncOp4 starts only after AsyncOp3 has completed
    ...
}

int main()
{
    ...
    Spawn( Script1 );
    Spawn( Script2 ); // Script1 and Script2 runs in parallel
    ...
    // TODO some machinery here :-)
    ...
    return 0;
}

My program should run multiple scripts at once, and each script should be a sequence of standard function calls (SyncOpX). The scripts can run in parallel because SyncOpX are implemented in terms of asynchronous functions (i.e., functions that start I/O operations, returns, and invoke callbacks when the I/O completes).

Of course, it would be easy to find a solution using multiple threads (Spawn creates a new thread and SynchOpX waits for the result of the asynchronous call). But I'm looking for a single thread solution, instead.

I think that coroutines could be used in some way. Since the current standard is C++14, is there a solution with boost coroutines? Or with any other [portable] mechanism?

BTW: I'm using boost::asio for async I/O.

Thanks.

Upvotes: 0

Views: 1091

Answers (1)

xlrg
xlrg

Reputation: 2109

If you already use boost.asio you should consider its spawn() and yield_context - http://www.boost.org/doc/libs/1_63_0/doc/html/boost_asio/reference.html#boost_asio.reference.spawn

Addtionally you could consider boost.fiber:

"One of the primary benefits of Boost.Fiber is the ability to use asynchronous operations for efficiency, while at the same time structuring the calling code as if the operations were synchronous."

Upvotes: 1

Related Questions