| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- 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)
- },
- })
- })
- }
- })
- }
- }
|