Skip to main content

Semaphore

import { Semaphore } from '@dr.pogodin/react-utils';

The Semaphore class implements a synchronization primitive which allows an async code to wait until the semaphore is set to the "ready" state, if it is not in that state already. A semaphore can be switched between "ready" and "non-ready" states as needed.

info

The Semaphore source code has been moved to JS Utils library, and it is re-exported from there; thus, it also can be imported as

import { Semaphore } from '@dr.pogodin/js-utils';

Properties

  • semaphore.readyboolean — Read-only. Current semaphore state.

Methods

constructor()

const semaphore = new Semaphore(ready = false);

Creates a new Semaphore instance.

Arguments

  • readyboolean — Optional. The initial semaphore state. Defaults false.

    note

    It is safe to pass in a non-boolean ready argument, it will be casted to boolean according to the usual JS rules.

seize()

semaphore.seize(): Promise;

Waits until the semaphore is "ready", and "seizes" it for the caller; i.e. it switches it to the "non-ready" state, resolves returned promise, and guarantees that no other pending seize() or waitReady() promises of this semaphore will be resolved until the current caller sets it back to the "ready" state. It also guarantees that all seize() and waitReady() calls will be resolved in the same order they were triggered, i.e. none of them will jump the "queue" of previous calls waiting for the semaphore.

note

Under the hood, a seize() call just waits for waitReady(true).

BEWARE

Prior to the library version v1.23.0 it was suggested that seize() is equivalent to

await semaphore.waitReady();
semaphore.setReady(false);

and in general, it held for NodeJS / browser runtimes, but relied on inner interplay of pending promises and setTimeout() calls, and there was no guarantee it would work in an environment with different implementation of promises and timers.

Starting with library v1.23.0 it is not guaranteed that in a situation when multiple non-seizing waitReady() calls are waiting for a semaphore, it won't resolve them all prior to the execution flow returning to a code waiting for any of these promises. You must explicitly seize() the semaphore when you need to guarantee mutual exclusion of different asynchronous code flows waiting for it.

setReady()

semaphore.setReady(ready);

Sets semaphore to the specified state.

Arguments

  • readyboolean — Target state.

    Note, it is safe to pass in a non-boolean ready argument, which will be casted to boolean according to the usual JS rules.

waitReady()

semaphore.waitReady(seize): Promise;

Creates a Promise which resolves as soon as the semaphore is in the "ready" state. Optionally, it can "seize" the semaphore when called with true argument.

Arguments

  • seizeboolean — Optional. If set, the call will act the same as seize().
BEWARE

Prior to the library version v1.23.0 it was suggested that seize() is equivalent to

await semaphore.waitReady();
semaphore.setReady(false);

and in general, it held for NodeJS / browser runtimes, but relied on inner interplay of pending promises and setTimeout() calls, and there was no guarantee it would work in an environment with different implementation of promises and timers.

Starting with library v1.23.0 it is not guaranteed that in a situation when multiple non-seizing waitReady() calls are waiting for a semaphore, it won't resolve them all prior to the execution flow returning to a code waiting for any of these promises. You must explicitly seize() the semaphore when you need to guarantee mutual exclusion of different asynchronous code flows waiting for it.