Subject: Re: [boost] [thread] Alternate future implementation and future islands.
From: Jeremy Maitin-Shepard (jeremy_at_[hidden])
Date: 2015-03-18 20:22:38
Giovanni Piero Deretta <gpderetta <at> gmail.com> writes:
> On Wed, Mar 18, 2015 at 4:08 AM, Jeremy Maitin-Shepard
> <jeremy <at> jeremyms.com> wrote:
> I complely removed the current then/next implementation in favor of a
> generic then that works with any waitable. This makes it explicit that
> you can compose future types (and in fact any waitable) as long as
> they provide a get_event.
> I removed 'next' completely to simplify the implementation. The
> optimization opportunity to save an allocation on the except case is
> probably not worth the complexity.
I think it is good to have, even if it is implemented using `then', since it
has the advantage that the function passed does not have to deal in futures.
It seems like implementing it more efficiently as you did could make sense
in a more polished version, though, since futures are a basic primitive and
it is best to minimize the overhead as much as possible.
> > 3. Since invoking future::then and future::next release ownership, it is
> > worth considering making them only work on rvalues. Whether the extra
> > compile-time error checking this buys is worth the added verbosity of having
> > to add std::move in some cases is not clear, though.
> the new free function then takes its waitable by value (so you have to
> move it). I'll leave the current signature of then as is for now for
> compatibility with the standard proposal and boost::future.
> The required RMW are definitely non neglegible. I tried to keep them
> at a minimum but they still have a cost.
> My original future implementation actually had thread safety switch
> but it would be terribly error prone.
Certainly it would be more error-prone than the thread-safe future, since
there would be no compile-time way to verify that the user isn't incorrectly
accessing it from multiple threads without external locking, but I'm not
sure that is a reason not to provide it. It seems it would be possible to
upgrade a thread-unsafe future to a thread-safe future, provided that there
is no race between the upgrade and marking the future ready. I think the
implementation would be pretty simple, in fact.
> Instead I'm studying a way for future to start as simply a deferred
> synchronous computation, but that can become asynchronous on request
> of another thread (via work stealing or work requesting for example).
This would be pretty useful functionality to add support for; I guess it
would complicate your approach a bit, though.
One other issue that came to mind: your current approach of using a
singly-linked list of waiters seems to pose a problem for a timed wait or
other "recovable" waits, since you can only remove a waiter if it is at the
front of the list. With only unique-ownership futures this might be okay,
if you prohibit waiting on a future from multiple threads at once, since
then the waiter for be guaranteed to remain at the front of the list.
However, with shared-ownership futures the problem would be unavoidable.
Therefore it might make sense to switch to a doubly-linked list; I guess
this will make the lock-free algorithms trickier.
> > Benchmarks (and unit tests) would also be particularly helpful.
> I have yet to find a good, fair, small and realistic benchmark for
> futures. Ideas are welcome.
I was thinking microbenchmarks, that would at least show the cost of
individual operations and allow comparing different design
choices/implementations. For instance, cost of getting value from ready
future, cost of waiting on ready future, cost of calling then on ready or
not-yet-ready future, etc.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk