public final class Tailrec extends Object
Tailrec e ensures that recursive futures are stack-safe.
Given the optimization that this library implements to avoid thread context switch, compositions are not stack-safe by default. It is necessary to wrap recursive computations with a Tailrec call:
public Future<Integer> factorial(Integer i) {
Tailrec.apply(() ->
if (i ==0) return Future.value(1);
else factorial(i - 1).map(j -> i * j);
)
}
This is just an example, there’s no reason to use Futures to implement a factorial function. Requiring the Tailrec call for recursive computations is a reasonable compromise since recursive futures are uncommon.
Even though the computation is wrapped by Tailrec, the execution still leverages the synchronous execution optimizations in batches. It executes the composition synchronously until it reaches the batch size and then uses a Promise to unwind the stack and then run the next batch.
The default batch size is defined by the system property “io.trane.future.defaultBatchSize”, which is 512 by default. Alternatively, it is possible to set the batch size when calling Tailrec.apply:
public Future<Integer> factorial(Integer i) {
Tailrec.apply(1024, () ->
if (i ==0) return Future.value(1);
else factorial(i - 1).map(j -> i * j);
)
}
Note that the first parameter defines the batch size as 1024. Typically, the users do not need to tune this parameter unless a StackOverflowException is thrown or the user wants to increase the batch size for performance reasons. Larger batches tend to improve performance but increase the risk of a StackOverflowException.
| Constructor and Description |
|---|
Tailrec() |
| Modifier and Type | Method and Description |
|---|---|
static <T> Future<T> |
apply(int batchSize,
java.util.function.Supplier<Future<T>> sup)
Runs the recursive future using the custom batch size.
|
static <T> Future<T> |
apply(java.util.function.Supplier<Future<T>> sup)
Runs the recursive future using the default batch size.
|
public static final <T> Future<T> apply(java.util.function.Supplier<Future<T>> sup)
Runs the recursive future using the default batch size.
sup - the supplier to be called on each recursion.public static final <T> Future<T> apply(int batchSize, java.util.function.Supplier<Future<T>> sup)
Runs the recursive future using the custom batch size.
batchSize - the custom batch size.sup - the supplier to be called on each recursion.Copyright © 2017. All Rights Reserved.