//#region src/debug/bus-pool.d.ts /** * Buffer pool for the zero-allocation bus transport. * * Two hard-coded tiers, chosen from observed watermarks: * * small — 4 KB × 8 buffers (stats batches, lifecycle messages, * metadata-only registry/buffers deltas) * large — 256 KB × 4 buffers (buffer-pixel payloads, large registry * samples; also covers thumbnail RT * readbacks after `maxDim=256` cap) * * The *worker* allocates the pool on boot and transfers every buffer * to the producer at once. The producer holds two free stacks, * `acquireSmall` / `acquireLarge` pop from them, messages are written * into the acquired buffer, and the buffer is transferred back to the * worker via `port.postMessage(buf, [buf])`. The worker decodes, * publishes on the `BroadcastChannel`, then bounces the buffer back * to the producer's pool via a `POOL_RELEASE` message. * * Steady state: zero allocations past boot. If a pool empties (the * consumer is slow returning buffers), we fall back to a one-off * `new ArrayBuffer(tier.size)`, emit a debug warning, and do NOT * return that buffer to the pool (detected by byteLength mismatch on * release). Warning counters are exposed via `stats()` so the app * can surface the number in the pane if ever exhaustion fires. */ /** Tier sizes / counts. Hard-coded; bump here if we ever see exhaustion. */ declare const POOL: { readonly small: { readonly size: number; readonly count: 8; }; readonly medium: { readonly size: number; readonly count: 4; }; readonly large: { readonly size: number; readonly count: 4; }; }; type PoolTier = 'small' | 'medium' | 'large'; interface PoolStats { smallFree: number; mediumFree: number; largeFree: number; /** Pool-exhaustion events since construction (one-off `new ArrayBuffer` happened). */ smallExhausted: number; mediumExhausted: number; largeExhausted: number; /** Release-with-unknown-size events (buffer was a one-off; GC'd instead of pooled). */ orphaned: number; } declare class BufferPool { private _smallFree; private _mediumFree; private _largeFree; private _smallExhausted; private _mediumExhausted; private _largeExhausted; private _orphaned; /** * Flips to true on the first `seed()` call. Before that, the pool * is empty by construction (the worker is still booting and hasn't * transferred buffers yet); any `acquire*` in that window is part * of the boot race and not a sign of actual shortage. We allocate * a one-off as normal but suppress the warning so it doesn't look * like a persistent leak. */ private _seeded; /** * Seed the pool with buffers transferred in from the worker. Called * once per `POOL_INIT` message. Safe to call repeatedly if the * worker ever needs to top up (rare; not wired today). */ seed(tier: PoolTier, bufs: ArrayBuffer[]): void; acquireSmall(): ArrayBuffer; acquireMedium(): ArrayBuffer; acquireLarge(): ArrayBuffer; /** * Push a buffer back onto its tier's free stack. Buffers that don't * match either tier's size are orphaned (they were one-off fallback * allocations) — let GC reclaim them rather than contaminating the * pool with mismatched sizes. */ release(buf: ArrayBuffer): void; stats(): PoolStats; dispose(): void; } /** Allocate one tier's worth of fresh buffers — called by the worker at boot. */ declare function allocateTier(tier: PoolTier): ArrayBuffer[]; /** * Mutable cursor handed to `drain*` functions so they can append * their typed-array bytes into a shared pool buffer. Each `copyTypedTo` * call writes a TypedArray's contents at the current offset and * returns a new same-typed view positioned at that offset, then * advances the cursor (4-byte aligned for downstream views). */ interface BufferCursor { buffer: ArrayBuffer; byteOffset: number; } /** * Copy `src`'s bytes into `cursor.buffer` at `cursor.byteOffset`, * return a same-typed view at that location, advance the cursor with * 4-byte alignment. * * After the producer transfers the buffer to the worker via * `postMessage(msg, [cursor.buffer])`, the returned view's underlying * ArrayBuffer is the worker's copy — `bc.postMessage(msg)`'s * structuredSerialize then copies the bytes into the BC delivery * queues for each subscriber. */ declare function copyTypedTo(cursor: BufferCursor, src: T): T; //#endregion export { BufferCursor, BufferPool, POOL, PoolStats, PoolTier, allocateTier, copyTypedTo }; //# sourceMappingURL=bus-pool.d.ts.map