Module: sync.mutex
Source: ./sync/mutex.reef
Overview
sync/mutex - Mutual exclusion primitives
Provides mutex (mutual exclusion lock) support by wrapping the runtime's reef_lock_t. Use these primitives for low-level synchronization when Active Objects are not suitable.
IMPORTANT: Prefer Active Objects over manual mutex usage. Active Objects
provide automatic locking via exclusive methods and are safer.
Usage: import sync.mutex import core.option // mutex_create returns Option[Mutex]: creation can fail, and it says so // in the type rather than in a flag on a half-built value. match mutex_create() Option_Some(m) => mutex_lock(m) // ... critical section ... mutex_unlock(m) mutex_destroy(m) end Option_None() => // the runtime could not allocate the lock end end match
For safer scoped locking, consider using guard patterns: let guard = mutex_guard_create(m) // ... critical section ... mutex_guard_release(guard)
Types
Mutex
Mutex wraps the runtime's reef_lock_t.
lock_ptr is the SINGLE source of truth for liveness: non-nil means usable,
nil means destroyed. There used to be a valid: bool alongside it, which
meant two fields could disagree and every operation had to pick one to
trust. Creation failure is now carried by the Option that mutex_create
returns, not by a flag inside a half-built value.
Fields:
| Name | Type |
|---|---|
lock_ptr |
pointer |
MutexGuard
Guard that automatically locks on create, must be released manually (Reef doesn't have destructors, so manual release is required)
Fields:
| Name | Type |
|---|---|
mutex |
Mutex |
locked |
bool |
Functions
fn lock_ptr_live(m: Mutex): bool
Liveness test. nil may only be named inside an unsafe block, so the
comparison lives here once instead of at every use site.
fn lock_level_user(): int
Lock level for user-level mutexes (highest level, locks last)
fn mutex_create(): option.Option[Mutex]
Create a new mutex, or None if the runtime could not allocate the lock.
ROADMAP §8.3: this used to return a Mutex whose valid field said whether
it actually worked, so a caller that forgot to check got an object that
silently did nothing -- mutex_lock on it was a no-op, which is the worst
possible failure mode for a mutual-exclusion primitive: the critical
section runs unprotected and nothing reports it.
There is deliberately NO mutex_create_or twin. _or suits a lookup whose
miss is ordinary; None here means the lock could not be created, and a
default mutex would be exactly the silent no-op this change removes.
fn mutex_is_valid(m: Mutex): bool
Whether the mutex is still usable, i.e. created and not yet destroyed.
This is a DERIVED predicate over lock_ptr, not a wrapper around a stored flag -- the flag is gone. Creation failure is reported by mutex_create's Option; this answers the separate question of use-after-destroy, which the Option cannot express because it is a later state change.
fn mutex_guard_create(m: Mutex): MutexGuard
Create a guard that locks the mutex
Procedures
proc mutex_destroy(m: Mutex)
Destroy a mutex (releases resources) WARNING: Ensure no threads hold the mutex when destroying
proc mutex_lock(m: Mutex)
Acquire the mutex (blocking) Will block until the mutex is available
proc mutex_unlock(m: Mutex)
Release the mutex WARNING: Only call if you hold the lock
proc mutex_guard_release(g: MutexGuard)
Release the guard (unlocks the mutex)
Generated by reefc doc