Skip to content

Instantly share code, notes, and snippets.

@magicoal-nerb
Last active April 23, 2026 23:11
Show Gist options
  • Select an option

  • Save magicoal-nerb/c6195f665c4d9eed21c6da0489d707d3 to your computer and use it in GitHub Desktop.

Select an option

Save magicoal-nerb/c6195f665c4d9eed21c6da0489d707d3 to your computer and use it in GitHub Desktop.
--!strict
-- deque; could be used as an object pool
-- magicoal_nerb :3
local Deque = {}
export type Deque<T> = {
elements: { T },
capacity: number,
cursor: number,
size: number,
}
local function wrap(a: number, b: number, c: number): number
-- Assumes a is an initial position, b is an offset,
-- and c as the size..
return (a + b - 1) % c + 1
end
function Deque.new<T>(
capacity: number,
dispatch: () -> (T)
): Deque<T>
local elements = {}
for i = 1, capacity do
elements[i] = dispatch()
end
return {
elements = elements,
capacity = #elements,
size = 0,
cursor = 1,
}
end
function Deque.empty<T>(self: Deque<T>): boolean
-- Returns if the current object pool is empty
return self.size == 0
end
function Deque.iterate<T>(self: Deque<T>, callback: (T) -> ())
-- Iterate through all of the objects
-- from front to back.
for i = 1, self.size do
local slot = wrap(self.cursor, i - 1, self.capacity)
callback(self.elements[slot])
end
end
function Deque.pushFront<T>(self: Deque<T>): T
assert(self.size <= self.capacity, "cannot reach capacity!")
-- Adds an element to the front of the array
local slot = wrap(self.cursor, -1, self.capacity)
self.cursor = wrap(self.cursor, -1, self.capacity)
self.size += 1
return self.elements[self.cursor]
end
function Deque.pushBack<T>(self: Deque<T>): T
assert(self.size <= self.capacity, "cannot reach capacity!")
-- Adds an element to the back of the array
local slot = wrap(self.cursor, self.size, self.capacity)
local value = self.elements[slot]
self.size += 1
return value
end
function Deque.front<T>(self: Deque<T>): T
-- Gets the front element
return self.elements[self.cursor]
end
function Deque.back<T>(self: Deque<T>): T
-- Gets the back element
return self.elements[wrap(self.cursor, self.size - 1, self.capacity)]
end
function Deque.popFront<T>(self: Deque<T>): T
-- Removes the front element, so we advance our cursor
assert(self.size >= 0, "object pool is already empty!")
local value = self.elements[self.cursor]
self.cursor = wrap(self.cursor, 1, self.capacity)
self.size -= 1
return value
end
function Deque.popBack<T>(self: Deque<T>): T
-- Removes the back element
assert(self.size >= 0, "object pool is already empty!")
local slot = wrap(self.cursor, self.size, self.capacity)
self.size -= 1
return self.elements[slot]
end
return Deque
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment