-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Something like promises #100
Comments
cc: @civodul for insight from somebody who has been using reply channels. |
Howdy @pukkamustard! In the cases where I use a "reply channel", it's typically a remote procedure call (RPC) pattern so I don't need multicast nor caching. There are cases in the Shepherd with some sort of multicast: for instance, if multiple fibers call Regarding the name, I'd avoid "promise" because it's already taken (comes from R5RS or perhaps earlier than that), including Probably worth checking what the Spritely folks think, too! Ludo'. |
Basically, that's a condition variable + atomic box holding the result, where the result may only be set once (and permission to read the premise is separated from permission to set the result, but that's easy to accomplish by letting the constructor return two objects.) (the atomicness might not even be necessary because of the condition variable, but I don't know if signal-condition!/wait-operation actually does the proper C acquire/release stuff ...) Low-level interface: (make-promise) -> promise object + setter (for RPC stuff, you can send (query . setter) to the remote channel inside a spawn-fiber for asyncness). higher-level: (force ...): wait-operation + read the box (eager ...): pre-signal the new promise (lazy ...) (delay ...): I don't think the single condition is sufficient for this. (I think it should be possible to implement them somehow, but I'm insufficiently familiar with the SRFI implementation to be sure and actually say how.) (async ...): make promise and spawn a fiber evaluating the expression and setting the result. Higher-level, somewhat more limited:
Just use About ‘multicast’: you get that for free because 'wait-operation' is ‘multicast’.
If the 'delay/lazy' part is potentially implementable, I would name it "promise" (or "premise", I need to look up proper spelling), because it is the same concept as the R5RS or SRFI stuff. #:prefix is a thing; module imports can easily be renamed. Or just add name it 'concurrent-promise' to avoid collisions. Also, perhaps at some point in the future, Fibers is made part of Guile itself, the SRFI-45 promised and Fiber promises can be unified! My naming proposal: |
Also, you need to wrap 'setter' in a weak reference to make sure that the promise contains a strong reference to setter) and some guardian stuff to signal a condition to tell that fiber to stop if nobody is interested in the result promise anymore, to make sure that the fiber stops eternally asking a potentially-dead remote fiber, wasting resources. (That's for pure querying stuff, should be optional as that's potentially undesired for more stateful stuff.) |
In Concurrent ML these are called There is an Apache-2.0 implementation in a Racket package: https://docs.racket-lang.org/syncvar/ |
It might be useful to add something like a condition that can hold arbitrary values. I'll call this a promise for the moment and it might expose something like this:
An example where this is useful would be to signal completion of a request with return value.
In some code bases (e.g. shepherd) a reply channel is used for something similar. A request is posted to a pool of worker along with a newly created channel that is used to send the return value of the request back to the requestee. Here an example from
(shepherd services)
:(
get-message*
is likeget-message
but also does timeout handling).Using promises this might be (omitting the timeout logic):
Code looks very similar, but there seem to be some differences:
From what I understand this can be implemented using
make-base-operation
. Still, this might be useful enough to include in fibers itself?Naming
The name
promise
is used in the manual as an example for monadic style concurrency. The promise proposed here does not force the usage of monads.Guile has promises for delayed execution (https://www.gnu.org/software/guile/manual/html_node/Delayed-Evaluation.html).
Maybe calling it something else would make sense.
The text was updated successfully, but these errors were encountered: