10.4 Futures for Parallelism

► |  | Reference: Racket

1 | Language Model
2 | Syntactic Forms
3 | Datatypes
4 | Structures
5 | Classes and Objects
6 | Units
7 | Contracts
8 | Pattern Matching
9 | Control Flow
10 | Concurrency
11 | Macros
12 | Input and Output
13 | Reflection and Security
14 | Operating System
15 | Memory Management
16 | Unsafe Operations
17 | Running Racket
| Bibliography
| Index

▼ | 10 | Concurrency

10.1 | Threads
10.2 | Synchronization
10.3 | Thread-Local Storage
10.4 | Futures for Parallelism
10.5 | Places: Coarse-grained Parallelism

On this page:

future
touch
current-future
future?
processor-count

top← prev up next →

#### 10.4`` Futures for Parallelism

> > > Parallelism with Futures in Guide: Racket introduces futures.

( require racket/future)

The bindings documented in this section are provided by the racket/future and racket libraries, but not racket/base.

> > > Currently, parallel support for future is enabled by default for Windows, Linux x86/x86_64, and Mac OS X x86/x86_64. To enable support for other platforms, use --enable-futures with configure when building Racket.

The future and touch functions from racket/future provide access to parallelism as supported by the hardware and operation system. In contrast to thread, which provides concurrency for arbitrary computations without parallelism, future provides parallelism for limited computations. A future executes its work in parallel (assuming that support for parallelism is available) until it detects an attempt to perform an operation that is too complex for the system to run safely in parallel. Similarly, work in a future is suspended if it depends in some way on the current continuation, such as raising an exception. A suspended computation for a future is resumed when touch is applied to the future.

“Safe” parallel execution of a future means that all operations provided by the system must be able to enforce contracts and produce results as documented. “Safe” does not preclude concurrent access to mutable data that is visible in the program. For example, a computation in a future might use set! to modify a shared variable, in which case concurrent assignment to the variable can be visible in other futures and threads. Furthermore, guarantees about the visibility of effects and ordering are determined by the operating system and hardware – which rarely support, for example, the guarantee of sequential consistency that is provided for thread-based concurrency. At the same time, operations that seem obviously safe may have a complex enough implementation internally that they cannot run in parallel. See also Parallelism with Futures.

( future thunk) → future?
thunk : (-> any)

( touch f) → any
f : future?

The future procedure returns a future value that encapsulates thunk. The touch function forces the evaluation of the thunk inside the given future, returning the values produced by thunk. After touch forces the evaluation of a thunk, the resulting values are retained by the future descriptor in place of thunk, and additional touches of the future descriptor return those values.

Between a call to future and touch for a given future, the given thunk may run speculatively in parallel to other computations, as described above.

> ( let ([f ( future ( lambda () (+ 1 2)))])
( list (+ 3 4) ( touch f)))

'(7 3)

( current-future) → any

Returns the descriptor for the future that is evaluating the current thunk. If not currently running inside a future thunk (or futures are disabled), returns #f.

( future? v) → boolean?
v : any/c

Returns #t if v is a future-descriptor value, #f otherwise.

( processor-count) → exact-positive-integer?

Returns the number of parallel computations units (e.g., processors or cores) that are available on the current machine.
top← prev up next →