Async CountDown LatchLoading saved progress…

Async CountDown Latch

An async countdown latch is a one-shot gate that stays closed until a fixed number of events have happened, then releases every waiter at once. You tell it up front how many events to wait for; each event calls countDown(), and anyone who called wait() resumes the moment the last event reports in. It is the async cousin of a countdown latch from concurrent programming (for example Java's CountDownLatch) — the tool for "run this once all N of those have finished."

Implement asyncBarrierLatch(count). It returns three functions: countDown() records one event, wait() returns a promise that resolves when the latch opens, and remaining() reports how many events are still needed.

Signature

type Latch = {
  countDown(): void; // record one event; the count-th call opens the latch
  wait(): Promise<void>; // resolves when the latch opens (now, if already open)
  remaining(): number; // events still needed before the latch opens
};

function asyncBarrierLatch(count: number): Latch;

Examples

const latch = asyncBarrierLatch(3);

latch.wait().then(() => console.log('all ready'));

latch.remaining(); // 3
latch.countDown(); // remaining 2
latch.countDown(); // remaining 1
latch.countDown(); // remaining 0 -> logs "all ready"
const latch = asyncBarrierLatch(2);

const a = latch.wait();
const b = latch.wait();

latch.countDown();
latch.countDown(); // a and b both resolve together

latch.wait(); // already open -> resolves immediately
latch.countDown(); // no-op: nothing left to count
latch.remaining(); // 0

Notes

  • Wait for the count, not the first call — the latch opens only after countDown() has run exactly count times, not on the first one.
  • Everyone resolves together — any number of wait() promises can be outstanding at once; they all resolve at the single moment the latch opens.
  • Late waiters resolve immediately — calling wait() after the latch is open returns an already-resolved promise. The latch never closes again.
  • Extra countDowns are no-ops — once remaining() reaches zero, further countDown() calls do nothing: the count never goes negative and waiters are never released twice.
  • Assume a valid count — you can assume count is an integer of at least 1. Each wait() resolves with undefined.
  • No timers — this is pure promise plumbing; countDown() drives every resolution. You never need setTimeout.

FAQ

How is a countdown latch different from a semaphore or mutex?
A latch is one-shot and counts down to release waiters: once it opens it stays open forever. A semaphore or mutex is reusable and gates entry by handing out permits and reclaiming them.
What happens if I call wait() after the latch has already opened?
It resolves immediately. The latch never closes again, so a late waiter never blocks — it gets an already-resolved promise.
Can the latch be reset and reused?
No — a countdown latch is single-use. Once remaining reaches zero it stays open; for a reusable rendezvous where parties meet round after round, use a cyclic barrier instead.
Loading editor…