Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
29 lines
1.1 KiB
TypeScript
29 lines
1.1 KiB
TypeScript
/**
|
|
* Preallocated, refcounted frame buffers. Raw 1080p frames are 3 MB; allocating
|
|
* one per frame is ~93 MB/s of external memory per stream and drives GC, so the
|
|
* gate and the source bus recycle buffers once every in-flight write is done.
|
|
*/
|
|
export class BufferPool {
|
|
private readonly free: Buffer[] = [];
|
|
private readonly refs = new Map<Buffer, number>();
|
|
/** Buffers allocated after construction; stays 0 in steady state. */
|
|
allocs = 0;
|
|
constructor(readonly size: number, prealloc: number) {
|
|
for (let i = 0; i < prealloc; i += 1) this.free.push(Buffer.alloc(size));
|
|
}
|
|
/** The caller owns one reference; `release()` it when done. */
|
|
get(): Buffer {
|
|
let buf = this.free.pop();
|
|
if (!buf) { this.allocs += 1; buf = Buffer.alloc(this.size); }
|
|
this.refs.set(buf, 1);
|
|
return buf;
|
|
}
|
|
retain(buf: Buffer): void { this.refs.set(buf, (this.refs.get(buf) ?? 0) + 1); }
|
|
release(buf: Buffer): void {
|
|
const n = (this.refs.get(buf) ?? 0) - 1;
|
|
if (n > 0) { this.refs.set(buf, n); return; }
|
|
if (n < 0) return; // not pool-owned or already free
|
|
this.refs.delete(buf);
|
|
this.free.push(buf);
|
|
}
|
|
}
|