Boost logo

Boost :

Subject: Re: [boost] Futures
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2015-01-14 12:04:19


On Wed, Jan 14, 2015 at 7:02 AM, Niall Douglas
<s_sourceforge_at_[hidden]> wrote:
> On 13 Jan 2015 at 12:57, Gottlob Frege wrote:
>
>> Let's see if I've captured everything:
>
> Let me rewrite your rewrite ...
>
>> - we want to get a value from (likely) another THREAD, and WAIT if it
>> is not yet ready UNTIL it is ready, (whatever THREAD WAIT UNTIL mean)
>> - a future (boost:: or std:: or hpx:: etc) is a (high-level!) wrapping
>> of that concept
>> - to be inter-operable we need the lower level concepts (in ALL-CAPS) exposed
>>
>> THREAD:
>> we actually don't need to completely define what "another" THREAD is,
>> we only need a partial definition of our OWN THREAD. ie the *thread of
>> execution* of the current code,
>> because any code (that we assume at some point runs) runs in some
>> "thread of execution" - whether user mode thread, kernel thread, HPX,
>> whatever...
>
> If you replaced the word THREAD with EXECUTION CONTEXT,

Yes, re-reading what I wrote, I think that was my point (whether
planned or not) - we don't need to think about threads, but execution
contexts.

> where that means any of the following:
>
> 1. Kernel thread (stackful, 1:1 mapping, probably with some real
> hardware concurrency, cooperative context switching preferred but if
> too long elapses you get preempted by a timer)
>
> 2. Process thread (stackful, M:N mapping onto kernel threads,
> cooperative context switching though the cooperative part may be done
> for you by a local process runtime e.g. Fiber, ASIO, HPX, WinRT)
>
> 3. Functional/monadic call sequence (stateful though stackless,
> because functional call sequence is always constexpr and must only
> propagate state changes forwards, it can be safely suspended at any
> time without issue e.g. Hana, Expected, future-promise incidentally)
>
> 4. Stackless coroutine (an elaboration of item 5, but you get to
> write your code in a slightly less fragmented way which may aid
> maintainability e.g. Coroutine, ASIO's duff device macros
> implementing these)
>
> 5. Event callback handler (stackless, state is usually passed via a
> single void * or equivalent (std::function), almost always a local
> process runtime calls you when something happens e.g. NT Kernel APCs,
> POSIX signals, POSIX AIO, ASIO)
>

yep, that's the idea.

> This may explain why I am so keen that the compiler can optimise a
> future-promise down to single digit opcodes. For EXECUTION CONTEXT 3
> and 5 the compiler's optimiser is fully and partially available, and
> can collapse whole sections of code.
>
>> What we really need is access to the _controller_ of that thread of
>> execution - ie typically the scheduler, but not a full scheduler
>> interface. In recent C++ proposals this has been called the
>> "execution agent", although I've been pushing for EXECUTION CONTEXT -
>> the C++ object/interface that controls the context of the execution of
>> the current set of instructions.
>
> This is what the Executors concept was supposed to provide. I've
> always felt that ASIO is THE standard C++ executor and indeed event
> handling and dispatch framework, so go standardise on that instead of
> reinventing wheels no one wants nor uses.
>
>> WAIT:
>> The running code needs to be able to get at its EXECUTION CONTEXT in
>> order to be able to ask it WAIT.
>> For a given EXECUTION CONTEXT, WAIT means stop "running" - stop using
>> CPU, etc. No further PROGRESS (which turns out to be a hard term to
>> define, but the committee is working on that)
>
> 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()?

> 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)

>
> PROGRESS applies equally to all five ways of doing tasklets above.
>
>> UNTIL:
>> Some *other* EXECUTION CONTEXT needs to be able to tell the
>> aforementioned EXECUTION CONTEXT to RESUME.
>
> Personally I'd add ABORT here too. Some ASIO operations which ought
> to count as tasklets can be aborted, indeed so can kernel threads on
> POSIX. I am unsure if i/o operations ought to be included in the five
> types of EXECUTION CONTEXT above.
>
>> The value is orthogonal - the value is just a memory location (unless
>> we abstract that away!) and can be set via atomic operations or
>> whatever. Once the value is set, you then call RESUME on the execution
>> agent. From a value point-of-view, what you want is just an
>> ObservableValue. ie when value is changed, call this callable
>> (function, lambda, whatever). Given an ObservableValue, and an
>> ExecutionAgent you can build a promise.
>
> Sounds good.
>
> Niall
>
> --
> ned Productions Limited Consulting
> http://www.nedproductions.biz/
> http://ie.linkedin.com/in/nialldouglas/
>
>
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk