Async binary FIFO intra-context lock — exclude a critical section.
Module mutex | Source packages/front/fw/src/io/sync/mutex.js | Deps none | Worker-safe yes
Resolve
const mutex = runtime.resolve('mutex');
const m = mutex.create();
// Returns: { acquire, release, tryAcquire, runExclusive, locked }
API
| Method | Signature | Returns |
|---|---|---|
create |
() => MutexInstance |
New instance |
m.acquire |
() => Promise<void> |
Waits for the lock |
m.release |
() => void |
Releases the lock |
m.tryAcquire |
() => boolean |
Acquires if free (sync) |
m.runExclusive |
(fn: () => Promise<T>) => Promise<T> |
acquire → fn → release |
m.locked |
getter boolean |
Lock state |
Semantics
acquire: iflocked === false, acquires immediately (microtask); otherwise FIFO queue.releasewithout a prioracquire→ throwsError('mutex: release on unlocked').runExclusive: guaranteed try/finally — releases even iffnthrows.- Not reentrant: an
acquirefrom insiderunExclusive→ deadlock.
Examples
Basic critical section
const mutex = runtime.resolve('mutex');
const m = mutex.create();
async function criticalOp() {
await m.acquire();
try {
await updateSharedState();
} finally {
m.release();
}
}
With runExclusive (recommended pattern)
const result = await m.runExclusive(async () => {
const data = await readAndUpdate();
return data;
});
Worker Usage
const worker = fw.createWorker(
async function ({ libs }) {
const m = libs.mutex.create();
await m.runExclusive(async () => {
// critical section in the worker
});
},
{ dependencies: ['mutex'] }
);
Notes
- Strict FIFO queue — waiters are served in arrival order.
- Not reentrant: attempting
acquirefrom inside → deadlock. - A semaphore with 1 permit = mutex, but prefer
mutexfor clarity of intent.
See also
- semaphore — N permits
- channel — producer/consumer communication
- cancellable — task cancellation