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)