Timeout, the ability to execute an expression for at most a specified
amount of time, is an essential ingredient of fault-tolerant and distributed
programming. Orc accomplishes timeout using pruning and the
The following program runs F for at most one second, publishing its result if
available and the value
Let( F | Rwait(1000) >> 0 )
In the auction example given previously, the auction may never complete if one of the bidders does not respond. We can add a timeout so that a bidder has at most 8 seconds to provide a bid:
def auction() = 0 def auction(b:bs) = val bid = b.ask() | Rwait(8000) >> 0 max(bid, auction(bs))
This version of the auction is guaranteed to complete within 8 seconds.
Sometimes, rather than just yielding a default value, we would like to
determine whether an expression has timed out, and if so, perform some other
computation. To detect the timeout, we pair the result of the original
true and the result of the timer with
Thus, if the expression does time out, then we can distinguish that case
using the boolean value.
Here, we run expression F with a time limit
t. If it publishes
within the time limit, we bind its result to
r and execute G.
Otherwise, we execute H.
val (r, b) = (F, true) | (Rwait(t), false) if b then G else H
Instead of using a boolean and conditional, we could use pattern matching:
val s = Some(F) | Rwait(t) >> None() s >Some(r)> G | s >None()> H
It is even possible to encapsulate timeout as a function.
def timeout(x, t) = Let(Some(x) | Rwait(t) >> None())
timeout(F, t) waits
t milliseconds for F to publish a value. If F publishes
the time limit,
Some(v). Otherwise, it returns
None() when the time limit is reached.
We can also apply timeout to streams. Let's
define a modified version of the
repeat function as follows:
def repeatWithTimeout(f, t) = timeout(f(), t) >Some(x)> (x | repeatWithTimeout(f, t))
f() as before, but apply a timeout of
t to the call.
If a value becomes available from
f before the timeout, then the call to
Some(x), which we match, and then publish
x and recursively wait for further values from the stream.
However, if no value is available from
f within the timeout, the call
not match the pattern, the entire expression halts, indicating that the end of the
stream has been reached.
It is also possible to achieve this behavior with the existing
simply by changing the function passed to
def f'() = timeout(f(), t) >Some(x)> x repeat(f')