Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/util/common/lock.ts
13397 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
/**
7
* A class representing a lock that can be acquired and released.
8
*/
9
export class Lock {
10
11
private _locked = false;
12
private _queue: (() => void)[] = [];
13
14
get locked(): boolean {
15
return this._locked;
16
}
17
18
/**
19
* Acquires the lock. If the lock is already acquired, waits until it is released.
20
*/
21
async acquire(): Promise<void> {
22
if (!this._locked) {
23
this._locked = true;
24
return;
25
}
26
27
await new Promise<void>((resolve) => {
28
this._queue.push(resolve);
29
});
30
await this.acquire();
31
}
32
33
/**
34
* Releases the lock and allows the next queued function to execute.
35
* If the lock is not currently locked, an error will be thrown.
36
*/
37
release(): void {
38
if (!this._locked) {
39
throw new Error('Cannot release an unlocked lock');
40
}
41
42
this._locked = false;
43
const next = this._queue.shift();
44
if (next) {
45
next();
46
}
47
}
48
}
49
50
export class LockMap {
51
52
private _locks: Map<string, Lock> = new Map();
53
54
async withLock<T>(key: string, fn: () => Promise<T>): Promise<T> {
55
if (!this._locks.has(key)) {
56
this._locks.set(key, new Lock());
57
}
58
59
const lock = this._locks.get(key)!;
60
61
await lock.acquire();
62
63
try {
64
return await fn();
65
} catch (error) {
66
throw error;
67
} finally {
68
lock.release();
69
}
70
}
71
}
72
73