Scheme 48 Manual | Contents | In Chapter: Threads
Previous: Mutual exclusion | Next: Mutual exclusion

## Mutual exclusion

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.

### Locks

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.

### Placeholders

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