On this page:
start_  atomic
end_  atomic
atomically
start_  uninterruptible
end_  uninterruptible
uninterruptibly
0.45+9.2.0.3

3.2 Atomic Mode and Uninterruptible Mode🔗ℹ

 import: ffi/atomic package: rhombus-ffi-lib

Atomic mode evaluates a Rhombus expression without switching among Rhombus coroutine threads and with limited support for synchronizable events. An atomic computation in this sense is not atomic with respect to parallel threads, but only to coroutine threads. Asynchronous break exceptions (in the sense of Thread.break) are also disabled in atomic mode.

Atomic mode is unsafe, because the Rhombus scheduler is not able to operate while execution is in atomic mode: (1) the scheduler cannot switch coroutine threads or poll certain kinds of events, which can lead to deadlock or starvation of other threads; and (2) calling a scheduler-related function in atomic mode has unspecified behavior, where misuse is not necessarily caught with a check. Functions that are directly scheduler-related include Thread, Thread.sleep, and Evt.sync. Beware that other operations can involve such synchronization, such as writing to an output port or using a mutable map. Even if an output target is known to be free of synchronization, beware that values can have arbitrary printing procedures attached through Printable. 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.

Uninterruptible mode is related to atomic mode. It is also unsafe and practically the same as atomic mode in a coroutine thread, but uninterruptible mode does not force a parallel thread to synchronize with all coroutine threads. Uninterruptible mode also allows the use of uncontested semaphores and mutable maps.

function

fun atomic.start_atomic() :: Void

 

function

fun atomic.end_atomic() :: Void

 

expression

atomic.atomically:

  body

  ...

The atomic.start_atomic function increments an internal atomic-mode counter, starting atomic mode if the counter was zero, and atomic.end_atomic decrements the atomic-mode counter, ending atomic mode if the counter becomes zero.

The atomic.atomically form uses try with atomic.start_atomic as an ~initially clause and atomic.end_atomic as a ~finally clause.

function

fun atomic.start_uninterruptible() :: Void

 

function

fun atomic.end_uninterruptible() :: Void

 

expression

atomic.uninterruptibly:

  body

  ...

Like atomic.start_atomic, atomic.end_atomic, and atomic.atomically, but for uninterruptible mode. Since uninterruptible mode is subsumed by by atomic mode, incrementing the uninterruptible-mode counter has no effect in atomic mode. In contrast, atomic mode must not be started during uninterruptible mode.