Futures¶
Usage
use Futures;
or
import Futures;
Containers for accessing the results of asynchronous execution.
A Future
object is a container that can store the result of an
asynchronous operation, which can be retrieved when the result is ready.
Usage¶
A valid Future
object is not created directly. Instead, a future may
be created by calling the async()
function, which takes as arguments
the function to be executed and all arguments to that function.
The following example demonstrates a trivial use of futures. Three computations are executed asynchronously.
use Futures;
config const X = 42;
const A = async(proc(x: int) { return 2 * x; }, X);
const B = async(proc(x: int) { return 3 * x; }, X);
const C = async(proc(x: int) { return 4 * x; }, X);
writeln(A.get());
writeln(B.get());
writeln(C.get());
Validity of Futures¶
A future that is initialized by a call to async()
or
Future.andThen()
is created in a valid state. Otherwise — for
example, when a future is declared but not initialized — the future is in
an invalid state and method calls other than Future.isValid()
on an
invalid future will halt()
. If such a future object is subsequently
assigned to by a call to async()
or Future.andThen()
, then
the future will become valid.
use Futures;
// F is a valid future
var F = async(proc(x: int) { return 99; }, 13);
const f = F.get();
// G is currently an invalid future
var G: Future(int);
// ...other things can happen here...
// G is now a valid future
G = async(proc(x: int) { return 42 + x; }, 23);
const g = G.get();
Task Arguments¶
The task argument in a call to async()
or Future.andThen()
may be a first-class function, or a
specially-constructed class or record.
Such a record must have both a proc this() method for the desired
computation and a proc retType type method that returns the return
type of the this() method. (The requirement for the retType method is
a currently limitation that is intended to be resolved in the future.)
For example:
use Futures;
config const X = 99;
proc foo(x: int) {
return (x:real)/3.1415926;
}
record Bar {
proc this(x: real) {
return x / 2;
}
proc retType type do return real;
}
const bar: Bar;
const A = async(foo, X);
const B = A.andThen(bar);
writeln(B.get());
Future Chaining¶
A continuation to a future (itself a future) can be created via the
Future.andThen()
method, which takes as its single argument a function
to be invoked asynchronously (with respect to other tasks) but strictly ordered
in execution after the result of the parent future is ready. The continuation
function takes a single argument, the result of the parent future.
The following examples demonstrate such chaining of futures.
use Futures;
config const X = 42;
const F = async(proc(x: int) { return 2 * x; }, X)
.andThen(proc(x: int) { return x + 7; })
.andThen(proc(x: int) { return 3 * x; });
writeln(F.get() == (3 * ((2 * X) + 7))); // prints "true"
use Futures;
config const X = 1234;
var F = async(proc(x:int) { return x:string; }, X)
.andThen(proc(x:string) { return(x.size); });
writeln(F.get()); // prints "4"
Future Bundling¶
A set of futures can be bundled via waitAll
, which takes a
variable number of futures as arguments and returns a new future whose return
type is a tuple of the return types of the arguments. The returned future is
ready only when all the future arguments are ready.
The following example demonstrate bundling of futures.
use Futures;
config const X = 23;
const A = async(proc(x: int) { return 5 + x; }, X);
const B = async(proc(x: int) { return 7 * x; }, X);
const C = async(proc(x: int) { return 11 - x; }, X);
const D = waitAll(A, B, C);
writeln(D.get()); // prints (28, 161, -12)
- record Future¶
A container that can store the result of an asynchronous operation, which can be retrieved when the result is ready.
A future is not created directly. Instead, one is created by calling the
async()
function or theFuture.andThen()
method on an already-existing future.- type retType¶
The return type of the future.
- proc init=(x: Future)¶
- proc get() : retType¶
Get the result of a future, blocking until it is available.
If the future is not valid, this call will
halt()
.
- proc isReady() : bool¶
Test whether the result of the future is available.
If the future is not valid, this call will
halt()
.
- proc andThen(in taskFn)¶
Asynchronously execute a function as a continuation of the future.
The function argument taskFn must take a single argument of type retType (i.e., the return type of the parent future) and will be executed when the parent future’s value is available.
If the parent future is not valid, this call will
halt()
.- Arguments:
taskFn – The function to invoke as a continuation.
- Returns:
A future of the return type of taskFn
- proc async(in taskFn)¶
Asynchronously execute a function (taking no arguments) and return a
Future
that will eventually hold the result of the function call.- Arguments:
taskFn – A function taking no arguments
- Returns:
A future of the return type of taskFn
- proc async(in taskFn, args ...)
Asynchronously execute a function (taking arguments) and return a
Future
that will eventually hold the result of the function call.- Arguments:
taskFn – A function taking arguments with types matching args
args – Arguments to taskFn
- Returns:
A future of the return type of taskFn
- proc waitAll(futures ...?N)¶
Bundle a set of futures and return a
Future
that will hold a tuple of the results of its arguments (themselves futures).- Arguments:
futures – A variable-length argument list of futures
- Returns:
A future with a return type that is a tuple of the return type of the arguments