Skip to content

Semaphore

Limits how many effects can use a shared resource at the same time.

A Semaphore owns a number of permits. Work can run only after acquiring the permits it needs, and those permits are returned when the work finishes. This module includes constructors, automatic wrappers that acquire and release permits around an effect, manual permit operations, a non-waiting variant for work that should only run immediately, and resizing support for an existing semaphore.

11 exports Added in v4.0.0 Source

Combinators

release

Added in v4.0.0 Source

Releases the specified number of permits and returns the resulting available permits.

When to use

Use when you need to return permits acquired with take in a lower-level permit protocol with explicit release control.

Details

Running the effect releases the requested permits, wakes waiting acquirers when permits become available, and returns the current available permit count.

Gotchas

Manual take / release usage must keep permit counts balanced. Prefer withPermit or withPermits when the acquisition can be scoped to one effect.

See

  • take for manually acquiring permits
  • releaseAll for returning every currently taken permit
  • withPermits for automatic acquire and release around an effect

Signature

declare const release: {
  (permits: number): (self: Semaphore) => Effect<number>;
  (self: Semaphore, permits: number): Effect<number>;
};

releaseAll

Added in v4.0.0 Source

Releases all permits held by this semaphore and returns the resulting available permits.

When to use

Use to return every currently taken permit to a semaphore at once, typically during cleanup of manual take / release protocols.

See

  • release for releasing a known permit count
  • withPermits for automatic acquire and release around an effect

Signature

declare function releaseAll(self: Semaphore): Effect<number>;

resize

Added in v4.0.0 Source

Sets the total number of permits managed by the semaphore.

When to use

Use to change the concurrency limit of an existing semaphore while keeping current acquisitions in place.

Details

Existing acquisitions remain taken after resizing. If the new total is less than the currently taken permit count, new acquisitions wait until enough permits are released.

See

  • make for creating a semaphore with an initial permit count
  • release for returning permits without changing semaphore capacity

Signature

declare const resize: {
  (permits: number): (self: Semaphore) => Effect<void>;
  (self: Semaphore, permits: number): Effect<void>;
};

take

Added in v4.0.0 Source

Acquires the specified number of permits and returns the acquired permit count.

When to use

Use when you need manual permit acquisition for a lower-level protocol with explicit acquisition and release control.

Details

The effect waits until enough permits are available.

See

  • withPermit for automatically acquiring and releasing one permit around an effect
  • withPermits for automatically acquiring and releasing multiple permits around an effect
  • takeIfAvailable for manually acquiring permits without waiting
  • release for returning manually acquired permits

Signature

declare const take: {
  (permits: number): (self: Semaphore) => Effect<number>;
  (self: Semaphore, permits: number): Effect<number>;
};

Acquires the specified number of permits only if they are immediately available.

When to use

Use when you need fail-fast manual permit acquisition for a lower-level protocol with explicit acquisition and release control.

Details

If enough permits are available, they are acquired and the effect returns true. Otherwise, the effect returns false immediately without acquiring any permits.

See

  • take for the variant that waits until permits are available
  • release for returning manually acquired permits
  • withPermitsIfAvailable for automatic acquisition and release around an effect

Signature

declare const takeIfAvailable: {
  (permits: number): (self: Semaphore) => Effect<boolean>;
  (self: Semaphore, permits: number): Effect<boolean>;
};

withPermit

Added in v4.0.0 Source

Runs an effect with a single permit and releases the permit when the effect completes.

When to use

Use to guard an effect with exactly one semaphore permit while automatically releasing that permit when the effect exits.

See

Signature

declare const withPermit: {
  (self: Semaphore): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>;
  <A, E, R>(self: Semaphore, effect: Effect<A, E, R>): Effect<A, E, R>;
};

withPermits

Added in v4.0.0 Source

Runs an effect with the given number of permits and releases the permits when the effect completes.

When to use

Use to run an effect while holding a specified number of semaphore permits for the duration of that effect.

Details

The effect waits until enough permits are available. Acquired permits are released when the wrapped effect exits.

See

Signature

declare const withPermits: {
  (self: Semaphore, permits: number): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>;
  <A, E, R>(self: Semaphore, permits: number, effect: Effect<A, E, R>): Effect<A, E, R>;
};

Runs an effect only if the specified number of permits are immediately available.

When to use

Use when guarded work should run only if the requested permits are immediately available.

Details

When the permits are unavailable, the effect is not run and the result is Option.none. When permits are available, the effect is run, its result is wrapped in Option.some, and the acquired permits are released when the effect exits.

See

  • withPermits for the variant that waits until permits are available

Signature

declare const withPermitsIfAvailable: {
  (self: Semaphore, permits: number): <A, E, R>(effect: Effect<A, E, R>) => Effect<Option<A>, E, R>;
  <A, E, R>(self: Semaphore, permits: number, effect: Effect<A, E, R>): Effect<Option<A>, E, R>;
};

Constructors

make

Added in v4.0.0 Source

Creates a Semaphore initialized with the specified total number of permits.

When to use

Use to create a semaphore inside Effect code for bounding concurrency with automatic or manual permit management.

Signature

declare function make(permits: number): Effect<Semaphore>;

makeUnsafe

Added in v4.0.0 Source

Creates a Semaphore synchronously with the specified total number of permits.

When to use

Use to construct a semaphore synchronously when an immediate value is required outside an Effect workflow.

Signature

declare function makeUnsafe(permits: number): Semaphore;

Models

Semaphore interface

Added in v4.0.0 Source

A counting semaphore that coordinates concurrent access with permits.

When to use

Use to coordinate concurrent effects that need bounded access to a shared resource.

Details

Effects can acquire permits, wait until enough permits are available, release permits, or run with permits that are automatically released when the effect exits.

See

  • make for creating a semaphore inside Effect code
  • makeUnsafe for creating a semaphore synchronously

Signature

interface Semaphore {
  readonly releaseAll: Effect<number>;
  release(this: Semaphore, permits: number): Effect<number>;
  resize(this: Semaphore, permits: number): Effect<void>;
  take(this: Semaphore, permits: number): Effect<number>;
  takeIfAvailable(this: Semaphore, permits: number): Effect<boolean>;
  withPermit<A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>;
  withPermits(
    this: Semaphore,
    permits: number,
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>;
  withPermitsIfAvailable(
    this: Semaphore,
    permits: number,
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<Option<A>, E, R>;
}