2021-04-20 21:58:50 +03:00
|
|
|
type LockInfo = [Promise<void>, () => void]
|
|
|
|
interface OneWayLinkedList<T> {
|
|
|
|
v: T
|
|
|
|
n?: OneWayLinkedList<T>
|
|
|
|
}
|
|
|
|
|
2021-04-18 16:23:25 +03:00
|
|
|
/** @internal */
|
|
|
|
export class Lock {
|
2021-04-20 21:58:50 +03:00
|
|
|
private _first?: OneWayLinkedList<LockInfo>
|
|
|
|
private _last?: OneWayLinkedList<LockInfo>
|
2021-04-18 16:23:25 +03:00
|
|
|
|
|
|
|
async acquire(): Promise<void> {
|
2021-04-20 21:58:50 +03:00
|
|
|
while (this._first) {
|
|
|
|
await this._first.v[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
let unlock: () => void
|
|
|
|
const prom = new Promise<void>((resolve) => {
|
|
|
|
unlock = resolve
|
2021-04-18 16:23:25 +03:00
|
|
|
})
|
2021-04-20 21:58:50 +03:00
|
|
|
|
|
|
|
if (this._last) {
|
|
|
|
this._last.n = { v: [prom, unlock!] }
|
|
|
|
this._last = this._last.n
|
|
|
|
} else {
|
|
|
|
this._first = this._last = { v: [prom, unlock!] }
|
|
|
|
}
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
release(): void {
|
2021-04-20 21:58:50 +03:00
|
|
|
if (!this._first) throw new Error('Nothing to release')
|
|
|
|
this._first.v[1]()
|
|
|
|
this._first = this._first.n
|
|
|
|
if (!this._first) this._last = undefined
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
|
|
|
}
|