import { invariant } from '../../invariant'; export interface Lock { abandon: () => void; } export interface LockAPI { isClaimed: () => boolean; isActive: (lock: Lock) => boolean; claim: (abandon: () => void) => Lock; release: () => void; tryAbandon: () => void; } export default function create(): LockAPI { let lock: Lock | null = null; function isClaimed(): boolean { return Boolean(lock); } function isActive(value: Lock): boolean { return value === lock; } function claim(abandon: () => void): Lock { invariant(!lock, 'Cannot claim lock as it is already claimed'); const newLock: Lock = { abandon }; // update singleton lock = newLock; // return lock return newLock; } function release() { invariant(lock, 'Cannot release lock when there is no lock'); lock = null; } function tryAbandon() { if (lock) { lock.abandon(); release(); } } return { isClaimed, isActive, claim, release, tryAbandon }; }