import { Heap } from './heap';
interface Semaphore {
    wait: Promise<void>;
    signal: () => void;
}
interface JobWaiting<T> {
    hash: T;
    prio: number;
    counter: number;
    start: Semaphore;
}
interface JobRunning<T> {
    hash: T;
    prio: number;
    finish: Semaphore;
}
/**
 * @type QueueStats {running: number, waiting: number, last: number}
 */
interface QueueStats {
    running: number;
    waiting: number;
    last: number;
}
export declare class Queue<T = unknown> {
    maxConcurrent: number;
    minCycle: number;
    queueRunning: Map<T, JobRunning<T>>;
    queueWaiting: Heap<JobWaiting<T>>;
    lastRun: number;
    nextTimer: Promise<void> | null;
    counter: number;
    /**
     * @class Queue
     *
     * Priority queue with rate limiting<br>
     * See the medium article:<br>
     * https://mmomtchev.medium.com/parallelizing-download-loops-in-js-with-async-await-queue-670420880cd6
     * (the code has changed a lot since that article but the basic idea of using Promises as locks remains the same)
     *
     * @param {number} [maxConcurrent=1] Number of tasks allowed to run simultaneously
     * @param {number} [minCycle=0] Minimum number of milliseconds between two consecutive tasks
     */
    constructor(maxConcurrent?: number, minCycle?: number);
    /**
     * @private
     */
    tryRun(): void;
    /**
     * Signal that the task `hash` has finished.<br>
     * Frees its slot in the queue
     *
     * @method end
     * @param {any} hash Unique hash identifying the task, Symbol() works very well
     */
    end(hash: T): void;
    /**
     * Wait for a slot in the queue
     *
     * @method wait
     * @param {any} hash Unique hash identifying the task
     * @param {number} [priority=0] Optional priority, -1 is higher priority than 1
     * @return {Promise<void>} Resolved when the task is ready to run
     */
    wait(hash: T, priority?: number): Promise<void>;
    /**
     * Run a job (equivalent to calling Queue.wait(), fn() and then Queue.end())<br>
     * fn can be both synchronous or asynchronous function
     *
     * @method run
     * @param {Function} job The job
     * @param {number} [priority=0] Optional priority, -1 is higher priority than 1
     * @return {Promise<any>} Resolved when the task has finished with the return value of fn
     */
    run<U>(job: () => Promise<U>, priority?: number): Promise<U>;
    /**
     * Return the number of running and waiting jobs
     *
     * @method stat
     * @return {QueueStats} running, waiting, last
     */
    stat(): QueueStats;
    /**
     * Returns a promise that resolves when the queue is empty
     * (or there are no more than <maxWaiting> waiting tasks
     * if the argument is provided)
     *
     * @method flush
     * @return {Promise<void>}
     */
    flush(maxWaiting?: number): Promise<void>;
}
export {};
