Skip to content

Commit ad9a72b

Browse files
committed
feat: exposing ChunkedQueue
Since it's a useful data structure, exposing it for external usage
1 parent 9856ea2 commit ad9a72b

4 files changed

Lines changed: 34 additions & 7 deletions

File tree

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ class Block<T> {
2121
}
2222
}
2323

24-
export class Queue<T> {
24+
/**
25+
* A memory-efficient FIFO queue optimized for high-throughput scenarios.
26+
* Uses fixed-size array blocks to minimize memory allocations and copying.
27+
* Suitable for scenarios with frequent enqueue/dequeue operations.
28+
*/
29+
export class ChunkedQueue<T> {
2530
private head?: Block<T>;
2631
private tail?: Block<T>;
2732
private _length = 0;
@@ -30,6 +35,10 @@ export class Queue<T> {
3035
this.push(item);
3136
}
3237

38+
/**
39+
* Adds an item to the end of the queue.
40+
* @param item The item to add.
41+
*/
3342
push(item: T): void {
3443
if (!this.tail || this.tail.isFull()) {
3544
const newBlock = new Block<T>();
@@ -41,6 +50,10 @@ export class Queue<T> {
4150
this._length++;
4251
}
4352

53+
/**
54+
* Removes and returns the oldest item of the queue.
55+
* @returns The oldest item of the queue, or undefined if the queue is empty.
56+
*/
4457
pop(): T | undefined {
4558
if (!this.head || this.head.isEmpty()) {
4659
if (!this.head?.next) return undefined;
@@ -51,13 +64,23 @@ export class Queue<T> {
5164
return item;
5265
}
5366

67+
/**
68+
* Processes and removes all items from the queue.
69+
* The callback may add more items to the queue during processing,
70+
* But it needs to take care of the logic to avoid infinite loops.
71+
* @param cb Callback function to process each item.
72+
*/
5473
exhaust(cb: (item: T) => void): void {
5574
while (this.length) {
5675
const item = this.pop() as T;
5776
cb(item);
5877
}
5978
}
6079

80+
/**
81+
* The number of items currently in the queue.
82+
* @returns The number of items in the queue.
83+
*/
6184
get length(): number {
6285
return this._length;
6386
}

libs/js-tuple/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './chunked-queue';
12
export * from './nested-map';
23
export * from './nested-set';
34
export * from './tuple';

libs/js-tuple/src/internal/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

libs/js-tuple/src/nested-map.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Queue } from './internal';
1+
import { ChunkedQueue } from './chunked-queue';
22
import { IterationOptions, PartialKey, TraverseMode, YieldMode } from './types';
33

44
const VAL = Symbol('value');
@@ -35,7 +35,7 @@ const EMPTY: PathArray = Object.freeze([]);
3535

3636
function pushToStackFactory<T extends boolean>(justValue: T) {
3737
return justValue
38-
? (stack: StackItem[] | Queue<StackItem>, stackItem: StackItem) => {
38+
? (stack: StackItem[] | ChunkedQueue<StackItem>, stackItem: StackItem) => {
3939
const { node } = stackItem;
4040
if (!node[MAP]?.size) return;
4141
for (const sub of node[MAP].values()) {
@@ -44,7 +44,7 @@ function pushToStackFactory<T extends boolean>(justValue: T) {
4444
});
4545
}
4646
}
47-
: (stack: StackItem[] | Queue<StackItem>, stackItem: StackItem) => {
47+
: (stack: StackItem[] | ChunkedQueue<StackItem>, stackItem: StackItem) => {
4848
const { node, path } = stackItem;
4949
if (!node[MAP]?.size) return;
5050
for (const [key, sub] of node[MAP].entries()) {
@@ -126,7 +126,7 @@ const traverser = {
126126
path: PathArray,
127127
justValue: T,
128128
): MapIterator<T extends 0 ? [K, V] : V> {
129-
const queue = new Queue({ node, path });
129+
const queue = new ChunkedQueue({ node, path });
130130
const getValue = getValueOpt[justValue] as (
131131
si: StackItem,
132132
) => T extends 0 ? [K, V] : V;
@@ -525,7 +525,11 @@ export class NestedMap<K, V> {
525525
base = treatKey(basePath);
526526
}
527527
const result = new NestedMap<K, V>();
528-
const queue = new Queue({ src: sourceNode, tgt: result.#root, path: base });
528+
const queue = new ChunkedQueue({
529+
src: sourceNode,
530+
tgt: result.#root,
531+
path: base,
532+
});
529533
queue.exhaust(({ src, tgt, path }) => {
530534
tgt[COUNT] = src[COUNT];
531535
if (src[SET]) tgt[SET] = src[SET];

0 commit comments

Comments
 (0)