Scheme 48 also has more traditional mutual-exclusion synchronization abstractions, specifically mutex locks and placeholders. Note that typically synchronization via optimistic concurrency is usually preferable: Mutual exclusion often puts the running program into an inconsistent state for the time of the inclusion, which has adverse effects on modularity and interruptibility.
The locks
structure contains bindings that implement standard
mutex locks:
(make-lock) -> lock
(lock? thing) -> boolean
(obtain-lock lock)
(maybe-obtain-lock lock) -> boolean
(release-lock lock)
Make-lock
creates a lock in the "released" state.
Lock?
is the predicate for locks.
Obtain-lock
atomically checks if lock
is in the
"released" state. If it is, the lock is put into the "obtained"
state, and obtain-lock
returns immediately. If the lock is in
the "obtained" state, the current thread is suspended and registered
with the lock.
Maybe-obtain-lock
, like obtain-lock
, checks the state of
lock
: if it is "released," the lock is put into the
"obtained" state, if it is "obtained," maybe-obtain-lock
returns immediately. Maybe-obtain-lock
returns #t
if
it was able to obtain the lock, and #f
otherwise.
Release-lock
does nothing if lock
is in the "released"
state. If it is in the "obtained" state, release-lock
causes one of the threads suspended on an obtain-lock
lock
operation to continue execution. If that thread is the last thread
registered with the lock, the lock is transferred to the "released"
state. In any case, release-lock
returns immediately.
The placeholders
structure contains bindings for
placeholders--thread-safe, write-once variables, akin to
ID-90 I-structures or CML I-variables.
The typical scenario for placeholders is that, say, a thread A computes a value needed by another thread B at some unspecified time. Both threads share access to a placeholder; when A has computed the value, it places it into the placeholder. When B needs the value, it extracts it from placeholder, blocking if necessary.
(make-placeholder) -> placeholder
(make-placeholder id) -> placeholder
(placeholder? thing) -> boolean
(placeholder-set! placeholder value)
(placeholder-value placeholder) -> value
Make-placeholder
creates an empty placeholder. (The optional
id
argument is only for debugging purposes; the discloser for
placeholders prints it out if present.) Placeholder?
is the
predicate for placeholders.
Placeholder-set!
places a value into a placeholder. Doing this
more than once signals an error. Placeholder-value
extracts
the value from the placeholder and returns it. If the placeholder is
empty, it blocks the current thread until it becomes full.
Previous: Mutual exclusion | Next: Mutual exclusion