/**
 * Deadline interruption for pyodide, which executes on THIS thread: a
 * busy guest loop blocks the event loop, so no timer here can ever
 * fire (the quickjs runtime has an in-VM interrupt hook for this;
 * pyodide only reads a SharedArrayBuffer via setInterruptBuffer). A
 * tiny watchdog worker owns the countdown instead: it writes SIGINT
 * (2) into the shared interrupt cell at the deadline, pyodide's
 * interpreter loop sees it mid-execution and raises KeyboardInterrupt,
 * and the run reports which trip happened through the second cell.
 *
 * Cells (Int32Array over one SharedArrayBuffer): [0] the pyodide
 * interrupt cell (pyodide resets it to 0 when it fires), [1] why the
 * trip happened (1 deadline, 2 kill signal), [2] the arm generation,
 * which the watchdog re-checks at the deadline so a countdown
 * cancelled just as it fires cannot poison the next run. Cell [3]
 * records an abort from the host before the worker has armed a run.
 *
 * Environments without SharedArrayBuffer or workers (a browser page
 * that is not cross-origin isolated) get null: runs stay unbounded
 * there, exactly the pre-interrupt behavior.
 */
export interface ArmedInterrupt {
    /**
     * Stop the countdown and report the trip. Idempotent: every later call
     * repeats the first answer, so the wrapper can disarm as soon as the
     * user code returns and the host can still read why it stopped.
     */
    disarm(): 'deadline' | 'signal' | null;
}
export interface PyodideInterrupter {
    /** The view to hand to pyodide.setInterruptBuffer, once. */
    readonly view: Int32Array;
    arm(timeoutSeconds: number | null, signal?: AbortSignal): ArmedInterrupt;
    close(): void;
}
export declare function createPyodideInterrupter(buffer?: SharedArrayBuffer): Promise<PyodideInterrupter | null>;
//# sourceMappingURL=interrupt.d.ts.map