Path: blob/main/extensions/copilot/src/util/common/lock.ts
13397 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45/**6* A class representing a lock that can be acquired and released.7*/8export class Lock {910private _locked = false;11private _queue: (() => void)[] = [];1213get locked(): boolean {14return this._locked;15}1617/**18* Acquires the lock. If the lock is already acquired, waits until it is released.19*/20async acquire(): Promise<void> {21if (!this._locked) {22this._locked = true;23return;24}2526await new Promise<void>((resolve) => {27this._queue.push(resolve);28});29await this.acquire();30}3132/**33* Releases the lock and allows the next queued function to execute.34* If the lock is not currently locked, an error will be thrown.35*/36release(): void {37if (!this._locked) {38throw new Error('Cannot release an unlocked lock');39}4041this._locked = false;42const next = this._queue.shift();43if (next) {44next();45}46}47}4849export class LockMap {5051private _locks: Map<string, Lock> = new Map();5253async withLock<T>(key: string, fn: () => Promise<T>): Promise<T> {54if (!this._locks.has(key)) {55this._locks.set(key, new Lock());56}5758const lock = this._locks.get(key)!;5960await lock.acquire();6162try {63return await fn();64} catch (error) {65throw error;66} finally {67lock.release();68}69}70}717273