* feat: moved tl-runtime to esm and native ArrayBuffers * feat: migration to esm * fix(core): web-related fixes * test: finally, some good fucking e2e * chore: fixed linters etc * ci: added e2e to ci * build(tl): fixed gen-code on node 20 * fix: codegen Uint8Array, not Buffer never `git reset --hard` kids * build: only do type-aware linting for `packages/*` * build: ignore no-unresolved in ci for e2e * fix: node 16 doesn't have subtle crypto apparently? * fix(tests): use Uint8Array for gods sake please can i just merge this already * ci: don't parallel tasks in ci because machines are utter garbage and it may just randomly break * ci: pass secrets to e2e tests * ci: separate cli command for ci apparently im retarded * fix: run codegen in e2e im actually retarded * ci: more fixes for e2e * ci: debugging stuff * ci: still debugging * ci: hopefully fix ci???
45 lines
1 KiB
TypeScript
45 lines
1 KiB
TypeScript
import { Deque } from './deque.js'
|
|
|
|
type LockInfo = [Promise<void>, () => void]
|
|
|
|
/**
|
|
* Simple class implementing a semaphore like
|
|
* behaviour.
|
|
*/
|
|
export class AsyncLock {
|
|
private _queue = new Deque<LockInfo>()
|
|
|
|
async acquire(): Promise<void> {
|
|
let info
|
|
|
|
while ((info = this._queue.peekFront())) {
|
|
await info[0]
|
|
}
|
|
|
|
let unlock: () => void
|
|
const prom = new Promise<void>((resolve) => {
|
|
unlock = resolve
|
|
})
|
|
|
|
this._queue.pushBack([prom, unlock!])
|
|
}
|
|
|
|
release(): void {
|
|
if (!this._queue.length) throw new Error('Nothing to release')
|
|
|
|
this._queue.popFront()![1]()
|
|
}
|
|
|
|
with(func: () => Promise<void>): Promise<void> {
|
|
let err: unknown = null
|
|
|
|
return this.acquire()
|
|
.then(() => func())
|
|
.catch((e) => void (err = e))
|
|
.then(() => {
|
|
this.release()
|
|
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
|
if (err) throw err
|
|
})
|
|
}
|
|
}
|