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