export default class Semaphore {
    constructor(count) {
        this.count = count;
        this.waiting = [];
    }


    acquire() {
        return new Promise((resolve, reject) => {
            if (this.count > 0) {
                this.count--;
                resolve();
            } else {
                this.waiting.push({
                    resolve,
                    reject
                });
            }
        });
    }


    release() {
        if (this.waiting.length > 0) {
            const {resolve} = this.waiting.shift();
            resolve();
        } else {
            this.count++;
        }
    }


    cancel() {
        while (this.waiting.length > 0) {
            const {reject} = this.waiting.pop();
            reject(new Error("Semaphore cancelled"));
        }
    }
}