5.9 Atomic Execution
(require ffi/unsafe/atomic) | package: base |
Atomic mode evaluates a Racket expression without switching among Racket threads and with limited support for events. An atomic computation in this sense is not atomic with respect to other places, but only to other threads within a place.
Atomic mode is unsafe, because the Racket scheduler is not able to operate while execution is in atomic mode; the scheduler cannot switch threads or poll certain kinds of events, which can lead to deadlock or starvation of other threads. Beware that many operations can involve such synchronization, such as writing to an output port. Even if an output target is known to be free of synchronization, beware that values can have arbitrary printing procedures attached through prop:custom-write. Successful use of atomic mode requires a detailed knowledge of any implementation that might be reached during atomic mode to ensure that it terminates and does not involve synchronization.
procedure
(start-atomic) → void?
procedure
(end-atomic) → void?
Note that pairing start-atomic and end-atomic with dynamic-wind is useful only when
the current exception handler is known to safely escape atomic mode, or else all possible escapes are through known continuation jumps or aborts (because breaks are disabled and no other exceptions are possible) that escape safely; and
exception constructions, if any, avoid printing values in the exception message, or else the error value conversion handler is always used and known to be safe for atomic mode.
Using call-as-atomic is somewhat safer than using start-atomic and end-atomic, because call-as-atomic catches exceptions and re-raises them after exiting atomic mode, and it wraps any call to the error value conversion handler with call-as-nonatomic. The latter is safe for a particular atomic region, however, only if the region can be safely interrupted by a non-atomic exception construction.
Unlike call-as-atomic, start-atomic and end-atomic can be called from any OS thread as supported by ffi/unsafe/os-thread, although the calls have no effect in that case.
See also the caveat that atomic mode is unsafe.
procedure
procedure
These functions are not significantly faster than start-atomic and end-atomic, so they provide no benefit in a context where breaks are disabled.
procedure
(call-as-atomic thunk) → any
thunk : (-> any)
When call-as-atomic is used in the dynamic extent of call-as-atomic, then thunk is called directly as a non-tail call.
If thunk raises an exception, the exception is caught and re-raised after exiting atomic mode. Any call to the current error value conversion handler is effectively wrapped with call-as-nonatomic.
See also the caveat that atomic mode is unsafe.
procedure
(call-as-nonatomic thunk) → any
thunk : (-> any)
When used not in the dynamic extent of a call to call-as-atomic, call-as-nonatomic raises exn:fail:contract.
procedure