"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
Object.defineProperty(exports, "__esModule", { value: true });
exports.SqlSemaphore = void 0;
exports.runWithSmartTraceSqlSemaphore = runWithSmartTraceSqlSemaphore;
exports.clearSmartTraceSqlSemaphoresForTests = clearSmartTraceSqlSemaphoresForTests;
/**
 * Small FIFO semaphore used by Smart Analysis Mode to keep nested per-scene SQL
 * pressure bounded. Legacy scene reconstruction does not opt in.
 */
class SqlSemaphore {
    constructor(maxConcurrent) {
        this.maxConcurrent = maxConcurrent;
        this.active = 0;
        this.queue = [];
        if (!Number.isInteger(maxConcurrent) || maxConcurrent < 1) {
            throw new Error(`SqlSemaphore maxConcurrent must be a positive integer, got ${maxConcurrent}`);
        }
    }
    async run(fn) {
        await this.acquire();
        try {
            return await fn();
        }
        finally {
            this.release();
        }
    }
    acquire() {
        if (this.active < this.maxConcurrent) {
            this.active += 1;
            return Promise.resolve();
        }
        return new Promise((resolve) => {
            this.queue.push(() => {
                this.active += 1;
                resolve();
            });
        });
    }
    release() {
        this.active = Math.max(0, this.active - 1);
        const next = this.queue.shift();
        if (next)
            next();
    }
}
exports.SqlSemaphore = SqlSemaphore;
const smartSemaphores = new Map();
function runWithSmartTraceSqlSemaphore(traceId, fn) {
    let semaphore = smartSemaphores.get(traceId);
    if (!semaphore) {
        semaphore = new SqlSemaphore(1);
        smartSemaphores.set(traceId, semaphore);
    }
    return semaphore.run(fn);
}
function clearSmartTraceSqlSemaphoresForTests() {
    smartSemaphores.clear();
}
//# sourceMappingURL=sqlSemaphore.js.map