mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-13 15:44:56 +00:00
chore: delete unused util/lock module (#27223)
This commit is contained in:
@@ -1,98 +0,0 @@
|
||||
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)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export * as Lock from "./lock"
|
||||
@@ -1,72 +0,0 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Lock } from "@/util/lock"
|
||||
|
||||
function tick() {
|
||||
return new Promise<void>((r) => queueMicrotask(r))
|
||||
}
|
||||
|
||||
async function flush(n = 5) {
|
||||
for (let i = 0; i < n; i++) await tick()
|
||||
}
|
||||
|
||||
describe("util.lock", () => {
|
||||
test("writer exclusivity: blocks reads and other writes while held", async () => {
|
||||
const key = "lock:" + Math.random().toString(36).slice(2)
|
||||
|
||||
const state = {
|
||||
writer2: false,
|
||||
reader: false,
|
||||
writers: 0,
|
||||
}
|
||||
|
||||
// Acquire writer1
|
||||
using writer1 = await Lock.write(key)
|
||||
state.writers++
|
||||
expect(state.writers).toBe(1)
|
||||
|
||||
// Start writer2 candidate (should block)
|
||||
const writer2Task = (async () => {
|
||||
const w = await Lock.write(key)
|
||||
state.writers++
|
||||
expect(state.writers).toBe(1)
|
||||
state.writer2 = true
|
||||
// Hold for a tick so reader cannot slip in
|
||||
await tick()
|
||||
return w
|
||||
})()
|
||||
|
||||
// Start reader candidate (should block)
|
||||
const readerTask = (async () => {
|
||||
const r = await Lock.read(key)
|
||||
state.reader = true
|
||||
return r
|
||||
})()
|
||||
|
||||
// Flush microtasks and assert neither acquired
|
||||
await flush()
|
||||
expect(state.writer2).toBe(false)
|
||||
expect(state.reader).toBe(false)
|
||||
|
||||
// Release writer1
|
||||
writer1[Symbol.dispose]()
|
||||
state.writers--
|
||||
|
||||
// writer2 should acquire next
|
||||
const writer2 = await writer2Task
|
||||
expect(state.writer2).toBe(true)
|
||||
|
||||
// Reader still blocked while writer2 held
|
||||
await flush()
|
||||
expect(state.reader).toBe(false)
|
||||
|
||||
// Release writer2
|
||||
writer2[Symbol.dispose]()
|
||||
state.writers--
|
||||
|
||||
// Reader should now acquire
|
||||
const reader = await readerTask
|
||||
expect(state.reader).toBe(true)
|
||||
|
||||
reader[Symbol.dispose]()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user