signature PROMISE structure Promise : PROMISE
The Promise structure provides operations to create and eliminate futures through explicit handles, so-called promises. The polymorphic function
promise ()
creates a new promise p and an associated future. The future can then be extracted with the function
future p
The future is eliminated by applying fulfill (p, v), which globally replaces it with the value v. That value may again be a future. A promise may not be fulfilled more than once.
Note: Promises may be thought of as single-assignment references that allow dereferencing prior to assignment, yielding a future. The operations promise, future and fulfill correspond to ref, ! and :=, respectively.
See the end of the page for some examples of programming with promises.
Imported implicitly.
signature PROMISE = sig type 'a promise type 'a t = 'a promise exception Promise val promise : unit -> 'a promise val future : 'a promise -> 'a val fulfill : 'a promise * 'a -> unit val fail : 'a promise * exn -> unit val isFulfilled : 'a promise * 'a -> unit end
The type of promises of values of type 'a.
Raised on multiple attempts to fulfill the same promise.
Creates a new promise and an associated future. Returns the promise.
Returns the future associated with p. If p has already been fulfilled with value v, that value is returned.
Replaces the future associated with p with the value v. If v is the future itself, the exception Future.Cyclic is raised instead. If p has already been fulfilled or failed, the exception Promise is raised.
Requests the exception ex and fails the future associated with the promise p with ex. If p has already been fulfilled or failed, the exception Promise is raised. Equivalent to
(Future.await ex; fulfill (p, spawn raise ex))
Returns true if p has already been fulfilled or failed, false otherwise. Note that a result of true does not necessarily imply that future p is determined, since p may have been fulfilled with another future.
Promises can be utilized to write a tail-recursive version of append:
fun append (l1, l2) = let val p = promise() in append'(l1, l2, p); future p end and append'( [], l2, p) = fulfill(p, l2) | append'(x::l1, l2, p) = let val p' = promise() in fulfill(p, x::future p'); append'(l1, l2, p') end
Channels can be implemented easily using promises and references:
type 'a chan = 'a list promise ref * 'a list ref fun chan () = let val p = promise () in (ref p, ref (future p)) end fun put ((putr, getr), x) = let val p = promise () in fulfill (Ref.exchange (putr, p), x :: future p) end fun get (putr, getr) = let val p = promise () val xs = Ref.exchange (getr, future p) in fulfill (p, tl xs); hd xs end fun close (putr, getr) = fulfill (!putr, nil)