Как сделать асинхронное программирование на C++ более линейным (сопрограммы?)

В C++14 я хотел бы создать механизм для использования асинхронных API "последовательным" способом, используя один поток.

Чтобы быть более явным, я хотел бы добиться что-то вроде этого:

// 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;
}

Моя программа должна запускать несколько сценариев одновременно, и каждый сценарий должен представлять собой последовательность стандартных вызовов функций (SyncOpX). Сценарии могут работать параллельно, потому что SyncOpX реализованы в терминах асинхронных функций (т. е. функций, которые запускают операции ввода-вывода, возвращают и вызывают обратные вызовы после завершения ввода-вывода).

Конечно, было бы легко найти решение, используя несколько потоков (Spawn создает новую тему и SynchOpX ждет результата асинхронного вызова). Но вместо этого я ищу решение с одним потоком.

Я думаю, что сопрограммы могут быть использованы в некотором роде. Поскольку текущий стандарт C++14Есть ли решение с boost coroutines? Или с любым другим [переносным] механизмом?

Кстати, я использую boost::asio для асинхронного ввода / вывода.

Благодарю.

1 ответ

Если вы уже используете boost.asio, вы должны рассмотреть его spawn() и yield_context - http://www.boost.org/doc/libs/1_63_0/doc/html/boost_asio/reference.html

Дополнительно вы можете рассмотреть boost.fiber:

"Одним из основных преимуществ Boost.Fiber является возможность использовать асинхронные операции для повышения эффективности, и в то же время структурировать вызывающий код, как если бы операции были синхронными".

Другие вопросы по тегам