feat: add O(1) deque
[poolifier.git] / src / queue.ts
CommitLineData
574b351d 1// Copyright Jerome Benoit. 2022-2023. All Rights Reserved.
13455ed2 2
29ee7e9a 3/**
574b351d 4 * Queue.
a0d41544
JB
5 *
6 * @typeParam T - Type of queue items.
29ee7e9a
JB
7 */
8export class Queue<T> {
e102732c
JB
9 private items!: T[]
10 private offset!: number
11 /** The size of the queue. */
12 public size!: number
13 /** The maximum size of the queue. */
14 public maxSize!: number
29ee7e9a 15
4d8bf9e4 16 public constructor () {
e102732c 17 this.clear()
6b27d407
JB
18 }
19
a0d41544
JB
20 /**
21 * Enqueue an item.
22 *
23 * @param item - Item to enqueue.
24 * @returns The new size of the queue.
25 */
4d8bf9e4 26 public enqueue (item: T): number {
116a8c86
JB
27 this.items.push(item)
28 ++this.size
29 if (this.size > this.maxSize) {
30 this.maxSize = this.size
31 }
4d8bf9e4 32 return this.size
29ee7e9a
JB
33 }
34
a0d41544
JB
35 /**
36 * Dequeue an item.
37 *
c318eb2f 38 * @returns The dequeued item or `undefined` if the queue is empty.
a0d41544 39 */
4d8bf9e4 40 public dequeue (): T | undefined {
116a8c86
JB
41 if (this.size <= 0) {
42 return undefined
29ee7e9a 43 }
116a8c86
JB
44 const item = this.items[this.offset]
45 if (++this.offset * 2 >= this.items.length) {
46 this.items = this.items.slice(this.offset)
47 this.offset = 0
48 }
49 --this.size
29ee7e9a
JB
50 return item
51 }
49be33fe
JB
52
53 /**
64383951 54 * Peeks at the first item.
116a8c86
JB
55 *
56 * @returns The first item or `undefined` if the queue is empty.
49be33fe
JB
57 */
58 public peek (): T | undefined {
116a8c86
JB
59 if (this.size <= 0) {
60 return undefined
61 }
62 return this.items[this.offset]
49be33fe 63 }
df593701
JB
64
65 /**
64383951 66 * Clears the queue.
df593701
JB
67 */
68 public clear (): void {
69 this.items = []
70 this.offset = 0
71 this.size = 0
72 this.maxSize = 0
73 }
b25a42cd
JB
74
75 /**
76 * Returns an iterator for the queue.
77 *
78 * @returns An iterator for the queue.
79 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
80 */
81 [Symbol.iterator] (): Iterator<T> {
82 const items = this.items
83 let i = this.offset
84
85 return {
86 next: () => {
87 if (i >= items.length) {
88 return {
89 value: undefined,
90 done: true
91 }
92 }
93 const value = items[i]
e677f6c5 94 ++i
b25a42cd
JB
95 return {
96 value,
97 done: false
98 }
99 }
100 }
101 }
29ee7e9a 102}