UNPKG

@deep-assistant/agent

Version:

A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.

99 lines (89 loc) 2.28 kB
export namespace Lock { const locks = new Map< string, { readers: number writer: boolean waitingReaders: (() => void)[] waitingWriters: (() => void)[] } >() function get(key: string) { if (!locks.has(key)) { locks.set(key, { readers: 0, writer: false, waitingReaders: [], waitingWriters: [], }) } return locks.get(key)! } function process(key: string) { const lock = locks.get(key) if (!lock || lock.writer || lock.readers > 0) return // Prioritize writers to prevent starvation if (lock.waitingWriters.length > 0) { const nextWriter = lock.waitingWriters.shift()! nextWriter() return } // Wake up all waiting readers while (lock.waitingReaders.length > 0) { const nextReader = lock.waitingReaders.shift()! nextReader() } // Clean up empty locks if (lock.readers === 0 && !lock.writer && lock.waitingReaders.length === 0 && lock.waitingWriters.length === 0) { locks.delete(key) } } export async function read(key: string): Promise<Disposable> { const lock = get(key) return new Promise((resolve) => { if (!lock.writer && lock.waitingWriters.length === 0) { lock.readers++ resolve({ [Symbol.dispose]: () => { lock.readers-- process(key) }, }) } else { lock.waitingReaders.push(() => { lock.readers++ resolve({ [Symbol.dispose]: () => { lock.readers-- process(key) }, }) }) } }) } export async function write(key: string): Promise<Disposable> { const lock = get(key) return new Promise((resolve) => { if (!lock.writer && lock.readers === 0) { lock.writer = true resolve({ [Symbol.dispose]: () => { lock.writer = false process(key) }, }) } else { lock.waitingWriters.push(() => { lock.writer = true resolve({ [Symbol.dispose]: () => { lock.writer = false process(key) }, }) }) } }) } }