Subject: Re: [boost] [next gen future-promise] What to call the monadic return type?
From: Avi Kivity (avi_at_[hidden])
Date: 2015-05-25 14:24:21


On 05/25/2015 07:37 PM, Niall Douglas wrote:
> On 25 May 2015 at 18:33, Avi Kivity wrote:
>
>>> In particular, error_code is fast, and unexpected returns are not
>>> exceptional and must be as fast as expected returns.
>> As I mentioned, in this case the user can use expected<> or similar
>> themselves.
> As I mentioned, expected<> is too hard on compile times for large
> code bases. It's also way overkill for what 98% of use cases need.
>
>> Otherwise, what's the type of error_code? There could be an
>> infinite amount of error_code types to choose from (starting with simple
>> 'enum class'es and continuing with error codes that include more
>> information about the error (nonscalar objects).
> It's std::error_code. Same as ASIO uses. If being compiled as part of
> Boost, I expect boost::error_code and boost::exception_ptr will work
> too as additional variant options.
>
>>> Also, any monadic transport would default construct to an unexpected
>>> state of a null error_code in fact, which is constexpr. This lets one
>>> work around a number of exception safety irritations where move
>>> constructor of T is not noexcept more easily.
>> I'm not sure how the default constructor of future<> and the move
>> constructor of T are related.
> Well, let's assume we're really talking about a maybe<T>, and
> future<T> subclasses maybe<T> with additional thread safety stuff.
>
> In this situation a maybe<T> doesn't need a default constructor, but
> because it's a fixed variant we always know that error_code is
> available, and error_code (a) doesn't allocate memory and (b) is STL
> container friendly, so it seems sensible to make maybe<T> also STL
> container friendly by letting it default to error_code.
>
> The problem, as with the WG21 proposed variant, is getting move
> assignment to not undefine behaviour the existing contents if the
> throwing move constructor throws. Boost Variant's copy constructor
> dynamically allocates a temporary copy of itself internally to give
> that strong guarantee - this is unacceptable overhead for mine. So I
> need some well defined state to default to if during move assignment
> my move constructor throws after I have destructed my current state.
> Defaulting to an error_code saying the move constructor threw is a
> reasonable well defined outcome.
>
>> I'm not even sure why future<> would require a default constructor.
>> Seastar's doesn't have one.
> My future promise is as close to a strict superset of the Concurrency
> TS as is possible. It should be drop in replaceable in 99% of use
> cases, with the only point of failure being if you are trying to use
> allocators with your futures.
>
> My future promise is also intended to enter the Boost.Thread rewrite
> as the next gen future promise, if it proves popular.
>
>>>>> ... turns into a "mov $5, %eax", so future<T> is now also a
>>>>> lightweight monadic return transport capable of being directly
>>>>> constructed.
>> I'm looking forward to it! I've been bitten by the same compile time
>> explosion problems and I'm curious to see how you solved them.
> With a great deal of concentrated study of compiler diagnostics and
> trial and error!
>
> Once they are working and they are being unit tested per commit, I'll
> get a CI failure every time I break it. That should make things
> enormously easier going. Lots of machinery and scripting to come
> before that though.
>
> I've got everything working except the sequence:
>
> promise<int> p;
> p.set_value(5);
> return p.get_future().get();
>
> This should reduce to a mov $5, %eax, but currently does not for an
> unknown reason. I'm just about to go experiment and see why.
>
>

I managed to get very close to this by sprinking always_inline
attributes, mostly at destructors.

As soon as the compiler makes a bad inlining decision, it loses track of
the values it propagated and basically has to undo all optimization.

It's still not perfect (one extra instruction) though.

(using gcc 5).