#include <boost/asio/steady_timer.hpp>
#include <trial/iofiber/fiber.hpp>
#include <iostream>

namespace asio = boost::asio;
namespace fib = trial::iofiber;
using namespace std;

int main()
{
  asio::io_context ioctx;

  fib::fiber f1{
    ioctx,
    [](fib::fiber::this_fiber this_fiber) {
      asio::steady_timer timer{this_fiber.get_executor().context()};

      cout << "3..." << flush;
      timer.expires_after(chrono::seconds(1));
      timer.async_wait(this_fiber);

      cout << " 2..." << flush;
      timer.expires_after(chrono::seconds(1));
      timer.async_wait(this_fiber);

      cout << " 1..." << endl;
      timer.expires_after(chrono::seconds(1));
      timer.async_wait(this_fiber);
    }
  };

  fib::fiber{
    ioctx,
    [&f1](fib::fiber::this_fiber this_fiber) {
      f1.join(this_fiber);

      cout << "Hello World" << endl;
    }
  }.detach();

  ioctx.run();
}

This library is not a competitor to Boost.Fiber. This library aims to have tight integration with Boost.Asio execution engine. User-level differences are:

  • Strand-aware primitives. Minimize the need for locks. Group fibers into strands and treat each group as an actor.

  • Interruption API. IO requests might never complete. Even if they might eventually complete we want to cancel them immediately to keep the application responsive. We need an interruption API that takes integration with Boost.Asio IO objects into account.

Boost.Asio already provides a stackful coroutine completion token. Reasons to use this library instead are:

  • Eventually you’ll want communication among coroutines and that’s when you’ll want fibers vocabulary.

  • You may be able to work around ASIO’s yield token by exploiting the token protocol, but as soon as you try to implement join() or sync primitives that work across different strands you’ll have a hard time.

I used the opportunity to build a library with some more goodies:

  • Based on Boost.Context newer APIs. No more deprecation warnings.

  • Associated executor is easy to extract.

  • Keep associated context busy until you call either join() or detach().

  • Easy API to do spurious yields.

  • Guaranteed post semantics (a.k.a. run-to-completion if you come from a JavaScript background).

  • Proper support for completion handlers with any number of arguments.

  • assert_excl_strand_ref<T> to mark blocks where suspension is forbidden.

  • Fiber local storage.

TODO:

  • Check issues page.

Check iofiber(7) to get started.