mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-31 06:12:26 +00:00
99 lines
2.2 KiB
TypeScript
99 lines
2.2 KiB
TypeScript
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)
|
|
},
|
|
})
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|