Path: blob/main/scripts/chat-simulation/fixtures/_chatperf_event.ts
13383 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// perf-benchmark-marker67/**8* Fixture for chat-simulation benchmarks.9* Simplified from src/vs/base/common/event.ts for stable perf testing.10*/1112import { IDisposable, DisposableStore } from './lifecycle';1314export interface Event<T> {15(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;16}1718export namespace Event {19export const None: Event<any> = () => ({ dispose() { } });2021export function once<T>(event: Event<T>): Event<T> {22return (listener, thisArgs?, disposables?) => {23let didFire = false;24const result = event(e => {25if (didFire) { return; }26didFire = true;27return listener.call(thisArgs, e);28}, null, disposables);29if (didFire) { result.dispose(); }30return result;31};32}3334export function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {35return (listener, thisArgs?, disposables?) =>36event(i => listener.call(thisArgs, map(i)), null, disposables);37}3839export function filter<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {40return (listener, thisArgs?, disposables?) =>41event(e => filter(e) && listener.call(thisArgs, e), null, disposables);42}4344export function debounce<T>(event: Event<T>, merge: (last: T | undefined, e: T) => T, delay: number = 100): Event<T> {45let subscription: IDisposable;46let output: T | undefined;47let handle: any;48return (listener, thisArgs?, disposables?) => {49subscription = event(cur => {50output = merge(output, cur);51clearTimeout(handle);52handle = setTimeout(() => {53const e = output!;54output = undefined;55listener.call(thisArgs, e);56}, delay);57});58return { dispose() { subscription.dispose(); clearTimeout(handle); } };59};60}61}6263export class Emitter<T> {64private readonly _listeners = new Set<(e: T) => void>();65private _disposed = false;6667readonly event: Event<T> = (listener: (e: T) => void) => {68if (this._disposed) { return { dispose() { } }; }69this._listeners.add(listener);70return {71dispose: () => { this._listeners.delete(listener); }72};73};7475fire(event: T): void {76if (this._disposed) { return; }77for (const listener of [...this._listeners]) {78try { listener(event); } catch { }79}80}8182dispose(): void {83if (this._disposed) { return; }84this._disposed = true;85this._listeners.clear();86}8788get hasListeners(): boolean { return this._listeners.size > 0; }89}9091export class PauseableEmitter<T> extends Emitter<T> {92private _isPaused = false;93private _queue: T[] = [];9495pause(): void { this._isPaused = true; }9697resume(): void {98this._isPaused = false;99while (this._queue.length > 0) {100super.fire(this._queue.shift()!);101}102}103104override fire(event: T): void {105if (this._isPaused) { this._queue.push(event); }106else { super.fire(event); }107}108}109110111