aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/utils/ConditionVariable.ts
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend/src/utils/ConditionVariable.ts')
-rw-r--r--subprojects/frontend/src/utils/ConditionVariable.ts64
1 files changed, 0 insertions, 64 deletions
diff --git a/subprojects/frontend/src/utils/ConditionVariable.ts b/subprojects/frontend/src/utils/ConditionVariable.ts
deleted file mode 100644
index 1d3431f7..00000000
--- a/subprojects/frontend/src/utils/ConditionVariable.ts
+++ /dev/null
@@ -1,64 +0,0 @@
1import PendingTask from './PendingTask';
2import getLogger from './getLogger';
3
4const log = getLogger('utils.ConditionVariable');
5
6export type Condition = () => boolean;
7
8export default class ConditionVariable {
9 private readonly condition: Condition;
10
11 private readonly defaultTimeout: number;
12
13 private listeners: PendingTask<void>[] = [];
14
15 constructor(condition: Condition, defaultTimeout = 0) {
16 this.condition = condition;
17 this.defaultTimeout = defaultTimeout;
18 }
19
20 async waitFor(timeoutMs?: number | undefined): Promise<void> {
21 if (this.condition()) {
22 return;
23 }
24 const timeoutOrDefault = timeoutMs ?? this.defaultTimeout;
25 let nowMs = Date.now();
26 const endMs = nowMs + timeoutOrDefault;
27 while (!this.condition() && nowMs < endMs) {
28 const remainingMs = endMs - nowMs;
29 const promise = new Promise<void>((resolve, reject) => {
30 if (this.condition()) {
31 resolve();
32 return;
33 }
34 const task = new PendingTask(resolve, reject, remainingMs);
35 this.listeners.push(task);
36 });
37 // We must keep waiting until the update has completed,
38 // so the tasks can't be started in parallel.
39 // eslint-disable-next-line no-await-in-loop
40 await promise;
41 nowMs = Date.now();
42 }
43 if (!this.condition()) {
44 log.error('Condition still does not hold after', timeoutOrDefault, 'ms');
45 throw new Error('Failed to wait for condition');
46 }
47 }
48
49 notifyAll(): void {
50 this.clearListenersWith((listener) => listener.resolve());
51 }
52
53 rejectAll(error: unknown): void {
54 this.clearListenersWith((listener) => listener.reject(error));
55 }
56
57 private clearListenersWith(callback: (listener: PendingTask<void>) => void) {
58 // Copy `listeners` so that we don't get into a race condition
59 // if one of the listeners adds another listener.
60 const { listeners } = this;
61 this.listeners = [];
62 listeners.forEach(callback);
63 }
64}