On 05/25/2015 12:37 PM, Niall Douglas wrote:
Dear list,
As AFIO looks likely to be finally getting a community review soon, I've made a start on a final non-allocating constexpr-collapsing next generation future-promise such that the AFIO you review is "API final". You may remember my experimentations on those from:
http://boost.2283326.n4.nabble.com/Non-allocating-future-promise-td466 8339.html.
Essentially the win is that future-promise generates no code at all on recent C++ 11 compilers unless it has to [1], and when it does it generates an optimally minimal set with no memory allocation unless T does so. This should make these future-promises several orders of magnitude faster than the current ones in the C++ standard and solve their scalability problems for use with things like ASIO. They also have major wins for resumable functions which currently always construct a promise every resumable function entry - these next gen future-promises should completely vanish if the resumable function never suspends, saving a few hundred cycles each call.
Anyway, my earlier experiments were all very promising, but they all had one big problem: the effect on compile time. My final design is therefore ridiculously simple: a future<T> can return only these options:
* A T. * An error_code (i.e. non-type erased error, optimally lightweight) * An exception_ptr (i.e. type erased exception type, allocates memory, you should avoid this if you want performance)
I believe error_code is unneeded. Exceptions are expected to be slow.
If you want another type of variant return, let the user encapsulate it
in T (could be optional<T>, or expected
In other words, it's a fixed function monad where the expected return is T, and the unexpected return can be either exception_ptr or error_code. The next gen future provides Haskell type monadic operations similar to Boost.Thread + Boost.Expected, and thanks to the constexpr collapse this:
future<int> test() { future<int> f(5); return f; } test().get();
... turns into a "mov $5, %eax", so future<T> is now also a lightweight monadic return transport capable of being directly constructed.
Can you post the code? I'd be very interested in comparing it with seastar's non-allocating futures.
In case you might want to know why a monadic return transport might be so useful as to be a whole new design idiom for C++ 11, try reading https://svn.boost.org/trac/boost/wiki/BestPracticeHandbook#a8.DESIGN:S tronglyconsiderusingconstexprsemanticwrappertransporttypestoreturnstat esfromfunctions.
However, future<T> doesn't seem named very "monadic", so I am inclined to turn future<T> into a subclass of a type better named. Options are:
* result<T> * maybe<T>
expected
Or anything else you guys can think of? future<T> is then a very simple subclass of the monadic implementation type, and is simply some type sugar for promise<T> to use to construct a future<T>.
Let the bike shedding begin! And my thanks in advance.
Niall
[1]: Compiler optimiser bugs notwithstanding. Currently only very recent GCCs get this pattern right. clang isn't bad and spills a dozen or so completely unnecessary opcodes, and I'll follow up with Chandler with some bug reports to get clang fixed. Poor old MSVC spits out about 3000 lines of assembler, it can't do constexpr folding at all yet.