Boost logo

Boost :

Subject: Re: [boost] Final lightweight monad, next gen futures and upcoming AFIO review (was: Re: [next gen futures] Lightweight monad r
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2015-06-26 07:00:45


On 26 Jun 2015 at 10:42, Andrzej Krzemienski wrote:

> > monad is now space optimal, consuming as little as two bytes
> > depending on configuration. monad<void> is now working, plus these
> > new specialisations were added:
> >
> > * result<T>: empty/T/error_code (no exception_ptr).
>
> To what run-time condition does an empty state correspond here? I used to
> thing that you either have a result (T) or a reason why you do not have one
> (error_code), but what does it mean that you have neither?

Semantically speaking, after feedback from this list, and having
attended Charley's C++ Now Presentation on ternary logic programming
"Your CPU is Binary", I realised that it's worthwhile to formally
specify future/monad/result as ternary logic primitives with ternary
logic operators. option<T> remains boolean. This gives the following
logic table:

Empty => False (future/monad/result/option)
Errored/Excepted => Indeterminate (future/monad/result)
Value => True (future/monad/result/option)

In other words, you never draw a distinction between errored and
excepted. They are semantically equivalent. Therefore not being
possible to be excepted in the case of result<T> means nothing, it's
simply a quality of implementation detail.

>From a non-semantic perspective, avoiding exception_ptr has *BIG*
benefits to runtime overhead because exception_ptr forces a memory
barrier, which is why MSVC spews ~2000 opcodes every time you use it.
Some of the time in promise-future you really don't require the
ability to transport arbitrary exceptions because an error_code is
enough, or maybe even no error transport is needed at all. Why
therefore pay for an exception transport when you don't need it? In
AFIO any time we go near OS APIs we currently convert the system
error code into an exception and throw it - this is total overkill.
Using result<T>, any time AFIO calls OS APIs it can exactly and
precisely wrap the outcome into a result<T> and not expend overhead
on unnecessary exception_ptr costs. Only if downstream code consumes
the result without checking for an error will a lazy conversion to an
exception throw occur.

This is why I hope these lightweight promise-futures will be
lightweight enough to promise-future a SHA256 round inside a budget
of 40 cycles because you can disable all error transport entirely,
and effectively just promise an async_optional<char[32]> as SHA256
cannot generate errors. Compare that to std::promise/future which
costs >= 530 CPU cycles per round, a little more than the SHA256
round itself.

I'm still unsure how to handle naming though. promise<T>/future<T>
obviously mean what they mean under the Concurrency TS, so they must
support exception_ptr. A promise-future only capable of transporting
a T and nothing else would need a descriptive name.

I'm currently thinking promise_option<T> and future_option<T>, but I
(a) find those too verbose and (b) I don't think the name means what
they do precisely. Any suggestions for a better name for a kind of
future which can only transport a T and nothing else is welcome.

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