|
Boost : |
Subject: Re: [boost] Futures
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2015-01-15 08:27:43
On 14 Jan 2015 at 12:04, Gottlob Frege wrote:
> > The key really is PROGRESS rather than wait. A future wait() or get()
> > halts PROGRESS of the calling EXECUTION CONTEXT
>
> sure but how does it halt - via some kernel/system/library/...
> mechanism, or does it call ExecutionContext->WAIT()?
You may have noticed my functional composure based futures test code
a few weeks ago. These work by taking some arbitrary sequence of
callable types (held in a tuple<c1, c2, ..., cL>) whose call operator
executes:
auto c5(c4(c3(c2(c1(...)))))
Now, what you do is to conceptualise a promise<T> as being
implemented by c1(T or exception_ptr or whatever value is being set)
... U cN(), and the future<T> as being implemented by cN+1(U) ...
cL() where L is the last callable in the heterogeneous sequence.
You now split the tuple between N and N+1 into two tuple sequences.
When you execute the first tuple sequence, you execute whatever your
custom promise type implementation is, and the output from its call
operator yields some storage type U. U is stored in the future. At
some later point, you now execute the second tuple sequence, which
takes the stored type U and _resumes_ the remainder of the original
tuple call sequence producing the original outcome of the original
tuple call sequence.
As abstract as this sounds, what we've done here is made arbitrary
heterogeneous sequences of functional calls pausable and resumable
using the same future and promise design already in C++, and with
remarkably little change except to reduce the design to its absolute
most essential fundamentals. One could therefore take some monadic
sequence written in Hana or Expected and arbitrarily pause and resume
its execution, including across kernel or user thread contexts. That,
I think, would be an enormous boon to practical functional
programming in C++.
So, to answer your original question "how does it halt?", I think the
only answer must be "according to its nature". Halting a kernel
thread is something only the kernel can do, halting a coroutine is
something only the coroutine implementation can do, and so on. Even
specifying a wait() function could be highly constraining e.g. to the
functional composure sequence I just mentioned, where we don't
wait(), we split().
> > until the PROGRESS of some other EXECUTION CONTEXT calls promise.set_value() or
> > set_exception().
>
> until some other code does whatever it wants, setting whatever it
> wants, and calls ExecutionContext->RESUME()
>
> ie separate the setting the value from the resuming of the execution.
>
> (The tricky part: while still maintaining atomicity where necessary)
The functionally composed promise futures are probably too far out
for the C++ community - I suspect even if I built them no one would
use them. I am grateful to the discussions here for making me realise
that though.
Instead in AFIO I'll implement a non-allocating afio::future<T> and
move onwards. No point flogging a dead horse here, besides I've had
some surprising recent success with a test implementation of a fast
(32784, 32768) SECDED error correcting code in software - I can
process 500Mb/sec, pretty amazing considering it's all bit work, but
to avoid pipeline stalls I need to combine the implementation with a
crypto hash (probably Blake2) and thus that probably has ruled out my
need for much faster futures which were originally demanded by my
SIMD 4-SHA256 engine. Given that CPUs next year will do SHA256 in
hardware, that renders that 4-SHA256 engine obsolete.
Funny really. I wrote that 4-SHA256 engine whilst I was still working
with you in BlackBerry. It's been a long road from then till now.
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