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