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