Promises in D
Vladimir Panteleev
thecybershadow.lists at gmail.com
Thu Apr 8 09:31:53 UTC 2021
On Thursday, 8 April 2021 at 07:39:44 UTC, Sebastiaan Koppe wrote:
> In short, they are eager. This means that they start running as
> soon as possible. That means the setValue of the promise and
> the attaching of the continuation can happen concurrently.
> Therefor space has to be allocated for the return value, as
> well as some sort of synchronization for the continuation
> handler.
>
> Senders/Receivers on the other hand are lazy. They don't start
> until after the receiver has been attached. Because of that it
> needs no allocation for the value, doesn't need to type-erase
> the continuation, and there is no concurrent access on the
> continuation handler.
>
> If you limit your program to a single thread you can avoid the
> concurrent access on the continuation handler, but that still
> leaves the value the promise produces, you still need to
> allocate that on the heap and ref count it.
>
> Because Senders/Receivers are lazy, there is less shared state
> and the ownership is simpler. On top of that they can often use
> the stack of whoever awaits them.
I see, thanks! So, if I understand correctly - to put it in
layman terms, senders/receivers is just a structured way to chain
together callables, plus propagating errors (as with promises),
plus cancellation. I understand that `setValue` just calls the
next continuation with its argument (as opposed to storing the
value somewhere as its name might imply), which means that the
value may reside on the stack of the sender's start function, and
remain valid only until `setValue` exits. The API is also
somewhat similar, and I understand the main distinction is that
starting execution is explicit (so, and the end of your `.then`
chain, there must be a `.start()` call OSLT).
> Senders/Receivers doesn't impose a specific execution model,
> you can use it on coroutines, threads, fibers, etc. In the
> implementation I focused on threads cause that is what we
> needed, but there isn't anything preventing from building an
> fiber scheduler on top of this.
I see how you could write a fiber-based executor/scheduler, but,
I don't see how you could use these as a base for a synchronous
fiber API like async/await. With delegates (and
senders/receivers), there is a known finite lifetime of the value
being propagated. With async/await, the value is obtained as the
return value of `await`, which does not really provide a way to
notify the value's source of when it is no longer needed.
More information about the Digitalmars-d
mailing list