Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/scripts/chat-simulation/fixtures/_chatperf_event.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/event.ts for stable perf testing.
11
*/
12
13
import { IDisposable, DisposableStore } from './lifecycle';
14
15
export interface Event<T> {
16
(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
17
}
18
19
export namespace Event {
20
export const None: Event<any> = () => ({ dispose() { } });
21
22
export function once<T>(event: Event<T>): Event<T> {
23
return (listener, thisArgs?, disposables?) => {
24
let didFire = false;
25
const result = event(e => {
26
if (didFire) { return; }
27
didFire = true;
28
return listener.call(thisArgs, e);
29
}, null, disposables);
30
if (didFire) { result.dispose(); }
31
return result;
32
};
33
}
34
35
export function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {
36
return (listener, thisArgs?, disposables?) =>
37
event(i => listener.call(thisArgs, map(i)), null, disposables);
38
}
39
40
export function filter<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {
41
return (listener, thisArgs?, disposables?) =>
42
event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
43
}
44
45
export function debounce<T>(event: Event<T>, merge: (last: T | undefined, e: T) => T, delay: number = 100): Event<T> {
46
let subscription: IDisposable;
47
let output: T | undefined;
48
let handle: any;
49
return (listener, thisArgs?, disposables?) => {
50
subscription = event(cur => {
51
output = merge(output, cur);
52
clearTimeout(handle);
53
handle = setTimeout(() => {
54
const e = output!;
55
output = undefined;
56
listener.call(thisArgs, e);
57
}, delay);
58
});
59
return { dispose() { subscription.dispose(); clearTimeout(handle); } };
60
};
61
}
62
}
63
64
export class Emitter<T> {
65
private readonly _listeners = new Set<(e: T) => void>();
66
private _disposed = false;
67
68
readonly event: Event<T> = (listener: (e: T) => void) => {
69
if (this._disposed) { return { dispose() { } }; }
70
this._listeners.add(listener);
71
return {
72
dispose: () => { this._listeners.delete(listener); }
73
};
74
};
75
76
fire(event: T): void {
77
if (this._disposed) { return; }
78
for (const listener of [...this._listeners]) {
79
try { listener(event); } catch { }
80
}
81
}
82
83
dispose(): void {
84
if (this._disposed) { return; }
85
this._disposed = true;
86
this._listeners.clear();
87
}
88
89
get hasListeners(): boolean { return this._listeners.size > 0; }
90
}
91
92
export class PauseableEmitter<T> extends Emitter<T> {
93
private _isPaused = false;
94
private _queue: T[] = [];
95
96
pause(): void { this._isPaused = true; }
97
98
resume(): void {
99
this._isPaused = false;
100
while (this._queue.length > 0) {
101
super.fire(this._queue.shift()!);
102
}
103
}
104
105
override fire(event: T): void {
106
if (this._isPaused) { this._queue.push(event); }
107
else { super.fire(event); }
108
}
109
}
110
111