簡體   English   中英

如何等待所有提升的完成:asio的堆棧協同程序?

[英]How to wait for completion of all boost:asio's stackful coroutines?

我正在使用asio :: spawn開始一些協同程序,我想等到所有這些都完成后再做其他工作。 怎么做?

控制流程如下:

asio::spawn (io, [] (asio::yield_context yield) {
  ...
  // starting few coroutines
  asio::spawn (yield, [] (asio::yield_context yield2) { ... });
  asio::spawn (yield, [] (asio::yield_context yield2) { ... });
  asio::spawn (yield, [] (asio::yield_context yield2) { ... });
  asio::spawn (yield, [] (asio::yield_context yield2) { ... });

  // now I want to wait for all of them to finish before I do 
  // some other work?
  ...
});

io.run ();

UPDATE

下面是示例代碼

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <chrono>

#include <iostream>
using namespace std;

int main ()
{
  using namespace boost::asio;

  io_service io;

  spawn (io, [&] (yield_context yield) {
    cout << "main coro starts\n";

    auto lambda = [&] (yield_context yield)
      {
        cout << "in lambda inside subcoroutine - starts\n";
        steady_timer t (io, std::chrono::seconds (1));
        t.async_wait (yield);
        cout << "in lambda inside subcoroutine - finishes\n";
      };

    // starting few coroutines
    spawn (yield, lambda);
    spawn (yield, lambda);

    // now I want to wait for all of them to finish before I do
    // some other work?
    // ???

    cout << "main coro finishes\n";
  });

  io.run ();
}

輸出是:

// main coro starts
// in lambda inside subcoroutine - starts
// in lambda inside subcoroutine - starts
// main coro finishes <----
// in lambda inside subcoroutine - finishes
// in lambda inside subcoroutine - finishes

雖然我期待:

// main coro starts
// in lambda inside subcoroutine - starts
// in lambda inside subcoroutine - starts
// in lambda inside subcoroutine - finishes
// in lambda inside subcoroutine - finishes
// main coro finishes

(參見“主要coro飾面”線的地方)

我找到了......一種解決方法。

我可以使用具有無限持續時間的計時器,並從最后的子協程中取消它。 這將喚醒主協程。

Coliru例子

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>

#include <iostream>
using namespace std;

int main ()
{
  using namespace boost::asio;

  io_service io;

  spawn (io, [&] (yield_context yield) {
    cout << "main coro starts\n";


    steady_timer rendez_vous (io, steady_timer::clock_type::duration::max ());
    /* volatile */ int counter = 2;


    auto lambda = [&] (yield_context yield)
      {
        cout << "in lambda inside subcoroutine - starts\n";
        steady_timer t (io, boost::chrono::seconds (1));
        t.async_wait (yield);
        cout << "in lambda inside subcoroutine - finishes\n";

        if (--counter == 0)
            rendez_vous.cancel ();
      };

    // starting few coroutines
    spawn (yield, lambda);
    spawn (yield, lambda);

    // now I want to wait for all of them to finish before I do
    // some other work?
    // ???
    boost::system::error_code ignored_ec;
    rendez_vous.async_wait (yield [ignored_ec]);
    // ignore errors here by reason.

    cout << "main coro finishes\n";
  });

  io.run ();
}

坦率地說,我不喜歡這個解決方案,因為它濫用“計時器”的概念和對象,這可能會浪費系統資源。

更好的選擇是使用光纖(boost.fiber集成到boost.asio中)。 boost :: fiber是一個協程+調度程序+同步類(像std :: thread這樣的API),可以像coroutines一樣在boost.asio上下文中使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM