"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeQ = makeQ;
const asap = globalThis.setImmediate || setTimeout;
function makeQ(parallelization = 1, max = Infinity) {
    const running = new Set();
    const queued = [];
    return {
        add(toAdd) {
            if (queued.length >= max + parallelization - running.size) // we may have some free slots that will be used at the next tick
                return false;
            queued.push(toAdd);
            asap(startNextIfPossible); // avoid calling now, as it would cause nesting/stacking of jobs
            return true;
        },
        isWorking() { return running.size > 0; },
        isFree() { return running.size < parallelization; },
        setMax(newMax) { max = newMax; },
        queueSize() { return queued.length; },
    };
    function startNextIfPossible() {
        while (running.size < parallelization) {
            const job = queued.shift();
            if (!job)
                break; // finished
            const working = job(); // start the job
            if (!working)
                continue; // it was canceled
            running.add(working);
            working.finally(() => {
                running.delete(working);
                startNextIfPossible();
            });
        }
    }
}
