Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/scripts/chat-simulation/fixtures/_chatperf_lifecycle.ts
13383 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
// perf-benchmark-marker
7
8
/**
9
* Fixture for chat-simulation benchmarks.
10
* Simplified from src/vs/base/common/lifecycle.ts for stable perf testing.
11
*/
12
13
export interface IDisposable {
14
dispose(): void;
15
}
16
17
export function isDisposable<T extends object>(thing: T): thing is T & IDisposable {
18
return typeof (thing as IDisposable).dispose === 'function'
19
&& (thing as IDisposable).dispose.length === 0;
20
}
21
22
export function dispose<T extends IDisposable>(disposable: T): T;
23
export function dispose<T extends IDisposable>(disposable: T | undefined): T | undefined;
24
export function dispose<T extends IDisposable>(disposables: T[]): T[];
25
export function dispose<T extends IDisposable>(disposables: readonly T[]): readonly T[];
26
export function dispose<T extends IDisposable>(arg: T | T[] | undefined): any {
27
if (Array.isArray(arg)) {
28
const errors: any[] = [];
29
for (const d of arg) {
30
try { d.dispose(); } catch (e) { errors.push(e); }
31
}
32
if (errors.length > 0) { throw new Error(`Dispose errors: ${errors.length}`); }
33
return arg;
34
} else if (arg) {
35
arg.dispose();
36
return arg;
37
}
38
}
39
40
export class DisposableStore implements IDisposable {
41
private readonly _toDispose = new Set<IDisposable>();
42
private _isDisposed = false;
43
44
dispose(): void {
45
if (this._isDisposed) { return; }
46
this._isDisposed = true;
47
this.clear();
48
}
49
50
clear(): void {
51
if (this._toDispose.size === 0) { return; }
52
const iter = this._toDispose.values();
53
this._toDispose.clear();
54
for (const item of iter) {
55
try { item.dispose(); } catch { }
56
}
57
}
58
59
add<T extends IDisposable>(o: T): T {
60
if (this._isDisposed) {
61
console.warn('Adding to a disposed DisposableStore');
62
return o;
63
}
64
this._toDispose.add(o);
65
return o;
66
}
67
68
get size(): number { return this._toDispose.size; }
69
}
70
71
export abstract class Disposable implements IDisposable {
72
private readonly _store = new DisposableStore();
73
74
dispose(): void {
75
this._store.dispose();
76
}
77
78
protected _register<T extends IDisposable>(o: T): T {
79
return this._store.add(o);
80
}
81
}
82
83
export class MutableDisposable<T extends IDisposable> implements IDisposable {
84
private _value?: T;
85
private _isDisposed = false;
86
87
get value(): T | undefined { return this._isDisposed ? undefined : this._value; }
88
89
set value(value: T | undefined) {
90
if (this._isDisposed || value === this._value) { return; }
91
this._value?.dispose();
92
this._value = value;
93
}
94
95
dispose(): void {
96
this._isDisposed = true;
97
this._value?.dispose();
98
this._value = undefined;
99
}
100
}
101
102
export class DisposableMap<K, V extends IDisposable> implements IDisposable {
103
private readonly _map = new Map<K, V>();
104
private _isDisposed = false;
105
106
set(key: K, value: V): void {
107
const existing = this._map.get(key);
108
if (existing !== value) {
109
existing?.dispose();
110
this._map.set(key, value);
111
}
112
}
113
114
get(key: K): V | undefined { return this._map.get(key); }
115
116
delete(key: K): void {
117
this._map.get(key)?.dispose();
118
this._map.delete(key);
119
}
120
121
dispose(): void {
122
if (this._isDisposed) { return; }
123
this._isDisposed = true;
124
for (const [, v] of this._map) { v.dispose(); }
125
this._map.clear();
126
}
127
}
128
129