mtcute/packages/core/src/utils/async-lock.ts
Alina Tumanova f5976a2d74
ESM + end-to-end tests (#11)
* 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???
2023-10-16 19:23:53 +03:00

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