refactor RingBuffer
This commit is contained in:
@@ -1,2 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
|
tsconfig.tsbuildinfo
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { expect, test } from "vitest";
|
||||||
|
import { claim, createRingBuffer } from "./RingBuffer.ts";
|
||||||
|
|
||||||
|
test("RingBuffer", () => {
|
||||||
|
expect(() => createRingBuffer(3, () => ({}))).toThrow(
|
||||||
|
"size must be a power of two",
|
||||||
|
);
|
||||||
|
|
||||||
|
const pooled = createRingBuffer(4, () => ({}));
|
||||||
|
|
||||||
|
expect(pooled.size).toBe(4);
|
||||||
|
expect(pooled.cursor).toBe(0);
|
||||||
|
expect(pooled.buffer.length).toBe(4);
|
||||||
|
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
expect(claim(pooled)).toBe(pooled.buffer[i % 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(pooled.cursor).toBe(0);
|
||||||
|
});
|
||||||
+25
-16
@@ -1,25 +1,34 @@
|
|||||||
export default class RingBuffer<T> {
|
export type Pooled<T> = {
|
||||||
size: number;
|
size: number;
|
||||||
mask: number;
|
mask: number;
|
||||||
cursor: number;
|
cursor: number;
|
||||||
buffer: Array<T>;
|
buffer: Array<T>;
|
||||||
|
};
|
||||||
|
|
||||||
constructor(size: number, blueprint: T) {
|
export function createRingBuffer<T extends object>(
|
||||||
if ((size & (size - 1)) !== 0) {
|
size: number,
|
||||||
throw new Error("size must be a power of two");
|
create: () => T,
|
||||||
}
|
): Pooled<T> {
|
||||||
|
if ((size & (size - 1)) !== 0) {
|
||||||
this.size = size;
|
throw new Error("size must be a power of two");
|
||||||
this.mask = size - 1;
|
|
||||||
this.cursor = 0;
|
|
||||||
this.buffer = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < size; i++) {
|
|
||||||
this.buffer.push(structuredClone(blueprint));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next(): T {
|
const buffer = new Array<T>(size);
|
||||||
return this.buffer[this.cursor++ & this.mask];
|
for (let i = 0; i < size; i++) {
|
||||||
|
buffer[i] = create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
size,
|
||||||
|
mask: size - 1,
|
||||||
|
cursor: 0,
|
||||||
|
buffer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function claim<T>(pooled: Pooled<T>): T {
|
||||||
|
const slot = pooled.buffer[pooled.cursor];
|
||||||
|
pooled.cursor = (pooled.cursor + 1) & pooled.mask;
|
||||||
|
|
||||||
|
return slot;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user