"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConcurrentSemaphore = void 0;
/**
 * Similar to the Semaphore but stops the execution on the Promise level instead of the whole thread.
 * @internal
 */
class ConcurrentSemaphore {
    constructor() {
        this.permits = undefined;
        this.queue = [];
    }
    /**
     * Acquires a permit to keep the execution.
     * @return a Promise that is completed once there is a permit available.
     */
    acquire() {
        // if permits is null, it means that the queue is unbounded.
        if (this.permits === undefined || this.permits === null) {
            return Promise.resolve();
        }
        // if there are enough permits, decrement it by one and allow the completable future to run.
        if (this.permits > 0) {
            this.permits--;
            return Promise.resolve();
        }
        // if there are no permit available, add the completable to the queue
        // and it will be allowed to run when another completable releases a permit.
        return new Promise((resolve, error) => {
            this.queue.push({ 'resolve': resolve });
        });
    }
    /**
     * Releases a permit and allows other Promises to run.
     */
    release() {
        // gets the next completable future from the queue.
        const nextPromise = this.queue.shift();
        if (nextPromise !== undefined) {
            // there is another completable future waiting to run, allow it but don't modify the number of permits.
            nextPromise.resolve();
        }
        else if (this.permits !== undefined && this.permits !== null) {
            // there is no completable waiting to run so just increment the number of available permits.
            this.permits++;
        }
    }
}
exports.ConcurrentSemaphore = ConcurrentSemaphore;
//# sourceMappingURL=concurrentSemaphore.js.map