Boost logo

Boost :

Subject: Re: [boost] Boost.Fiber review January 6-15
From: Oliver Kowalke (oliver.kowalke_at_[hidden])
Date: 2014-01-10 12:46:22

2014/1/10 Niall Douglas <s_sourceforge_at_[hidden]>

> Where I am finding things harder is what yield means to ASIO which
> takes a callback function of specification void (*callable)(const
> boost::system::error_code& error, size_t bytes_transferred) so fiber
> yield must supply a prototype matching that specification. You said
> above this:
> > - yield is an instance of boost::fibers::asio::yield_context which
> > represents the fiber running this code; it is used by asio's async result
> > feature
> >
> > - yield[ec] is put to an async-operation in order suspending the current
> > fiber and pass an error (if happend during execution of async-op) back to
> > the calling code, for instance EOF if socket was closed
> So I figure that yield will store somewhere a new bit of context, do
> a std::bind() encapsulating that context and hand off the functor to
> ASIO. ASIO then schedules the async i/o. When that completes, ASIO
> will do an io_service::post() with the bound functor, and so one of
> the fibers currently executing run() will get woken up and will
> invoke the bound functor.
> So far so good. But here is where I fall down: the fibre receives in
> an error state and bytes transferred, and obviously transmits that
> back to the fiber which called ASIO async_read() by switching back to
> the original context. I would understand just fine if yield()
> suspended the calling fiber, but it surely cannot because yield()
> will get executed before ASIO async_read() does as it's a parameter
> to async_read(). So I therefore must be missing something very
> important, and this is why I am confused. Is it possible that yield()
> takes a *copy* of the context like setjmp()?
> It's this kind of stuff which documentation is for, and why at least
> one person i.e. me needs hand holding through mentally groking how
> the ASIO support in Fiber works. Sorry for being a bit stupid.

you have to distinct between to 'yield' symbols - in the context of fibers
without ASIO
, e.g. calling boost::this_fiber::yield() the current fiber is supended at
added at the end of
the ready-queue of the fiber-scheduler (the fiber will be resumed if
dequeued from this list).

the other case you are referring to is the async-feature of boost.asio.
Chris has already
implemented the async-feature for coroutines (from boost.coroutine). so the
best source
of the internal working is the docu of boost.asio.
I've added support of asio's async-feature for fibers, e.g. if provided
some classes required
to use fibers in the context of asio and its async-operations (for instance
async_read() see examples).
usaly this code should belong to boost.asio instead boost.fiber - anyway,
because boost.fiber
is new I've added it in my lib.

the yield instance you use with the async-ops of asio (async_read() for
isntance) is a global of
type yield_t. this type holds an error_code as member and
operator[error_code &] let you
retrieve the error_code from the async-op.

boost::fibers::asio::spawn() is the function which starts a new fiber

Boost list run by bdawes at, gregod at, cpdaniel at, john at