Skip to content

Commit 6bd70c8

Browse files
committed
Use unrolled list as a pool with current ref
1 parent ba2c0a8 commit 6bd70c8

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

JavaScript/7-current.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
'use strict';
2+
3+
class QueueNode {
4+
length = 0;
5+
6+
constructor({ size }) {
7+
this.size = size;
8+
this.buffer = new Array(size).fill(null);
9+
this.reset();
10+
}
11+
12+
reset() {
13+
this.readIndex = 0;
14+
this.writeIndex = 0;
15+
this.next = null;
16+
}
17+
18+
enqueue(item) {
19+
if (this.writeIndex >= this.size) return false;
20+
this.buffer[this.writeIndex++] = item;
21+
this.length++;
22+
return true;
23+
}
24+
25+
dequeue() {
26+
if (this.length === 0) return null;
27+
const index = this.readIndex++;
28+
const item = this.buffer[index];
29+
this.buffer[index] = null;
30+
this.length--;
31+
return item;
32+
}
33+
}
34+
35+
class UnrolledQueue {
36+
#length = 0;
37+
#nodeSize = 1024;
38+
#poolSize = 2;
39+
#head = null;
40+
#tail = null;
41+
#current = null;
42+
43+
constructor(options = {}) {
44+
const { nodeSize, poolSize } = options;
45+
if (nodeSize) this.#nodeSize = nodeSize;
46+
if (poolSize) this.#poolSize = poolSize;
47+
48+
let first = new QueueNode({ size: nodeSize });
49+
let node = first;
50+
for (let i = 1; i < poolSize; i++) {
51+
node.next = new QueueNode({ size: nodeSize });
52+
node = node.next;
53+
}
54+
node.next = first;
55+
56+
this.#head = first;
57+
this.#current = first;
58+
this.#tail = node;
59+
}
60+
61+
get length() {
62+
return this.#length;
63+
}
64+
65+
enqueue(item) {
66+
if (!this.#head.enqueue(item)) {
67+
if (this.#head.next === this.#current) {
68+
const node = new QueueNode(this.#nodeSize);
69+
node.next = this.#head.next;
70+
this.#head.next = node;
71+
if (this.#tail === this.#head) this.#tail = node;
72+
}
73+
this.#head = this.#head.next;
74+
this.#head.enqueue(item);
75+
}
76+
this.#length++;
77+
}
78+
79+
dequeue() {
80+
if (this.#length === 0) return null;
81+
const item = this.#current.dequeue();
82+
this.#length--;
83+
if (this.#current.length === 0 && this.#current !== this.#head) {
84+
const node = this.#current;
85+
this.#current = this.#current.next;
86+
node.reset();
87+
this.#tail.next = node;
88+
this.#tail = node;
89+
}
90+
return item;
91+
}
92+
}
93+
94+
// Usage
95+
96+
const mq = new UnrolledQueue({ nodeSize: 8, poolSize: 2 });
97+
98+
for (let id = 0; id < 5; id++) {
99+
mq.enqueue({ id });
100+
}
101+
102+
while (mq.length) {
103+
const task = mq.dequeue();
104+
console.log(`Processing ${task.id}`);
105+
}
106+
107+
for (let id = 100; id < 105; id++) {
108+
mq.enqueue({ id });
109+
}
110+
111+
while (mq.length) {
112+
const task = mq.dequeue();
113+
console.log(`Processing ${task.id}`);
114+
}

0 commit comments

Comments
 (0)