Boost logo

Boost :

Subject: Re: [boost] [afio] Formal review of Boost.AFIO
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2015-08-25 10:29:57


On 25 Aug 2015 at 22:07, TONGARI J wrote:

> > 2. The reason why it's shared_ptr<handle> not handle * is precisely
> > because of how to manage lifetime over unknown continuations. If the
> > user writes:
> >
> > future<> oh=async_file("niall.txt");
> > future<> reads[100];
> > for(size_t n=0; n<100; n++)
> > reads[n]=async_read(oh, buffers[n], 10, n*4096);
> >
> > So this schedules niall.txt to be opened, and then adds 100
> > continuations onto that file open each of which schedules the read of
> > 10 bytes from a 4Kb multiple. All those 100 continuations occur in
> > *parallel*, and could complete in *any* order.
> >
> > So how do you keep the handle to the niall.txt file around until the
> > last continuation using that file has completed which is at some,
> > unknown point in the future? The natural fit is shared_ptr. It's
> > exactly what it was designed for.
> >
> > Does this make sense?
>
>
> I think it's an design issue, I wonder if it's possible to design the API
> around the ASIO model, e.g.
>
> ```
> afio::file file(io); // move-only
> await file.async_open("niall.txt");
> future<size_t> reads[100];
> for(size_t n=0; n<100; n++)
> reads[n] = file.async_read(buffers[n], 10, n*4096);
> ```
>
> Drop the dependency based API, since the forthcoming coroutine should solve
> it for you elegantly.

If C++ 1z coroutines were universally available, I'd strongly
consider something like this approach. But they are not, nor will
they be for many years yet.

The free function dependency based API abstracts away the concurrency
runtime actually used so end user code doesn't need to care. So, AFIO
might be configured to use C++ 1z coroutines, or ASIO, or
Boost.Fiber.

Code written to use AFIO is meanwhile identical and doesn't need to
think about any underlying concurrency runtime.

> This way, you don't need shared semantic for future<>, just like how we
> used to do with ASIO.

I do see the point. But also remember that thanks to Monad, shared
future semantics does not necessarily mean a whole shared_future
implementation in there. I can configure a custom future with
identical overheads to a lightweight future<T> but with shared future
semantics using a third party shared_ptr lifetime thanks to aliasing
shared_ptr.

In other words, the shared future handle to a file in afio::future<>
is close to zero extra cost under Monad. That doesn't answer whether
shared future semantics are good design or not, but it does mean that
traditional assumptions about overheads and costs which led to the
general rejection of futures in ASIO don't necessarily apply here.

And futures are exactly the right model for specifying ordering
constraints which are extremely important for lock free file i/o. As
much as I wish reference counting could be avoided, I also like
generality of API. The AFIO API presented I believe allows a good
balance of not caring about under the bonnet for end user code with
performance. Especially as reference counting has neglible overhead
compared to file i/o.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ 
http://ie.linkedin.com/in/nialldouglas/



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk