
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/