On 27 Jul 2015 at 17:03, Bjorn Reese wrote:
Future continuations are fine when the sequence from start to end doesn't branch. I am cautious of their usefulness in the general case still. It isn't uncommon to make choices in a completion handler to queue different async actions with different completion handlers.
You hit the nail on the head. This is one of the main reasons why I seldomly use futures for asynchronous operations. Instead I prefer coroutines (and callbacks for simple sequences) over futures as the use of future continuations quickly becomes unwieldy in reality. async_result gives me the freedom to choose whatever mechanism is appropriate for my application.
I agree with this, up until C++ 1z coroutines being part of the language. They too can work with any arbitrary synchronisation mechanism same as async_result, however the traits specialisation to enable an arbitrary synchronisation mechanism is rather more involved than async_result. Still, I am working under the assumption that with C++ 1z coroutines that people have access to an async_result equivalent, so I don't need to provide one myself.
I suspect that Niall's preference for (his own) futures is due to something that has only been mentioned briefly in this discussion.
AFIO operations are launched in a two-step process:
1. An operation is scheduled for execution (e.g. dispatcher::file() for opening a file.) 2. The operation is executed (e.g. dispatcher::call().)
Using this two-step approach allows us to schedule batches of dependent operations before they are executed.
When we batch operations together we should be able to express dependencies between them. Niall uses his own futures for that.
Correct. In the new v1.4 API things have slightly changed to become more obvious to write for the typical programmer: // This code uses v2 of the AFIO ABI using namespace BOOST_AFIO_V2_NAMESPACE; // Schedule a file open for writing future<> fileopened=async_file("foo.txt", file_flags::write); // Schedule a gather write to the file once it has opened future<> filewritten=async_write(fileopened, buffers, 0); // Schedule a fsync once the file has finished being written to future<> fileinstorage=async_sync(filewritten); // Schedule a file close once the previous fsync has completed future<> fileclosed=async_close(fileinstorage); All that happens asynchronously without blocking. If you'd like to know how an operation went, simply get() its future. In other words, the future returned carries happens-before dependency to any operations scheduled upon that future. Internally the above free functions quite literally expand into: return precondition.then(detail::async_xxx(pars...)) ... in fact internally, under the yet to be written lightweight futures engine, the engine itself is nothing but chains of future continuations. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/