/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ interface ILimitedTaskFactory { factory: ITask>; c: (value: T | Promise) => void; e: (error?: unknown) => void; } interface ITask { (): T; } /** * A helper to queue N promises and run them all with a max degree of parallelism. The helper * ensures that at any time no more than M promises are running at the same time. * * Taken from 'src/vs/base/common/async.ts' */ export class Limiter { private _size = 0; private runningPromises: number; private readonly maxDegreeOfParalellism: number; private readonly outstandingPromises: ILimitedTaskFactory[]; constructor(maxDegreeOfParalellism: number) { this.maxDegreeOfParalellism = maxDegreeOfParalellism; this.outstandingPromises = []; this.runningPromises = 0; } get size(): number { return this._size; } queue(factory: ITask>): Promise { this._size++; return new Promise((c, e) => { this.outstandingPromises.push({ factory, c, e }); this.consume(); }); } private consume(): void { while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) { const iLimitedTask = this.outstandingPromises.shift()!; this.runningPromises++; const promise = iLimitedTask.factory(); promise.then(iLimitedTask.c, iLimitedTask.e); promise.then(() => this.consumed(), () => this.consumed()); } } private consumed(): void { this._size--; this.runningPromises--; if (this.outstandingPromises.length > 0) { this.consume(); } } }