import { EventHub, type ListenerErrorPayload } from './event-hub.js'; import { ObservableValue } from './observable-value.js'; /** * Thrown by {@link Semaphore.execute} on a disposed semaphore, and used as * the rejection reason for pending tasks when the semaphore is disposed. */ export declare class SemaphoreDisposedError extends Error { constructor(); } export type SemaphoreEvents = { /** Fired when a queued task begins execution */ taskStarted: undefined; /** Fired when a running task resolves successfully */ taskCompleted: undefined; /** Fired when a running task rejects, carrying the thrown error */ taskFailed: { error: unknown; }; /** Fired when an event listener throws during emission */ onListenerError: ListenerErrorPayload; }; /** * An async semaphore that limits concurrent task execution to a fixed number of slots. * * Extends {@link EventHub} with {@link SemaphoreEvents} for per-task lifecycle events * (`taskStarted`, `taskCompleted`, `taskFailed`). * * Exposes individual {@link ObservableValue} counters for reactive state monitoring. * * @example * ```ts * const results = await usingAsync(new Semaphore(3), async (semaphore) => { * semaphore.pendingCount.subscribe((count) => console.log('Pending:', count)) * semaphore.subscribe('taskCompleted', () => console.log('A task completed')) * * return await Promise.all( * urls.map((url) => semaphore.execute(({ signal }) => fetch(url, { signal }))), * ) * }) * ``` */ export declare class Semaphore extends EventHub { private readonly queue; private readonly running; private disposed; /** The number of tasks waiting in the queue to be started */ readonly pendingCount: ObservableValue; /** The number of tasks currently executing */ readonly runningCount: ObservableValue; /** The total number of tasks that have resolved successfully */ readonly completedCount: ObservableValue; /** The total number of tasks that have rejected */ readonly failedCount: ObservableValue; private _maxConcurrent; constructor(maxConcurrent: number); getMaxConcurrent(): number; /** * Updates the concurrency limit. Raising it drains queued tasks into the * new slots immediately. Lowering it leaves running tasks alone — new * tasks queue until running count drops below the new limit. Throws on * non-positive integers. */ setMaxConcurrent(value: number): void; /** * Queues `task` for execution. The task receives an `AbortSignal` that * aborts when the caller's signal aborts (if provided) or when the * semaphore is disposed. Returns a promise resolving/rejecting with the * task's own result. Throws {@link SemaphoreDisposedError} synchronously * when called on a disposed semaphore. */ execute(task: (options: { signal: AbortSignal; }) => Promise, options?: { signal?: AbortSignal; }): Promise; private removePending; private drain; private cleanupCallerSignal; private startTask; /** * Disposes the semaphore: rejects all pending tasks with {@link SemaphoreDisposedError}, * aborts the signal of every running task, and disposes all observable counters and event listeners. */ [Symbol.dispose](): void; } //# sourceMappingURL=semaphore.d.ts.map