Skip to main content

GoodPool

A flexible and lightweight generic object pool.

GoodPool allows you to reuse objects instead of repeatedly creating and destroying them. You provide a function to create the object, another to initialize it when acquired, and an optional one to destroy it when the pool is cleaned.

local tblPool = GoodPool.new(
	function()
		return { value = 10 }
	end,
	function(tbl)
		tbl.value = 10
	end
)

local obj = tblPool:Get()
obj.value += 10
print(obj.value) -- 20

tblPool:Return(obj)
print(tblPool:Get().value) -- 10

Functions

new

GoodPool.new(
createFn() → T,--

Called when the pool is empty and a new object is needed.

initFn(T) → (),--

Called every time an object is acquired. Use this to reset its state.

destroyFn((T) → ())?--

Called on each object when Clean is invoked. Use this to free resources.

) → GoodPool<T>

Creates a new GoodPool.

forInstance

GoodPool.forInstance(
templateOrClassNameInstance | string,--

An existing Instance to clone, or a class name string to create one from.

setupFn(Instance) → ()--

Called every time an Instance is acquired. Use this to reset its state.

) → GoodPool<Instance>,Instance

Creates a GoodPool that clones Instances from a template.

If a class name string is provided, a new Instance of that class is created and used as the template. The template is returned alongside the pool so you can reference it later regardless of how it was created.

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local partPool, template = GoodPool.forInstance(
	ReplicatedStorage.Part,
	function(part)
		part.Transparency = 0
		part.Position = Vector3.new(0, 0, 0)
	end
)

print(template == ReplicatedStorage.Part) -- true

local part = partPool:Get()
part.Parent = workspace

partPool:Return(part)

Get

GoodPool:Get() → T

Retrieves an object from the pool, passing it through initFn before returning.

If the pool is empty, a new object is created via createFn.

Preload

GoodPool:Preload(
amountnumber--

Number of objects to pre-fill the pool with.

) → ()

Pre-fills the pool with a given number of objects created via createFn.

Useful for avoiding lag spikes on first use. Does nothing if amount is <= 0.

Resize

GoodPool:Resize(
newAmountnumber--

The desired pool size.

) → ()

Resizes the pool to the given amount.

If newAmount is greater than the current size, new objects are created via Preload. If newAmount is less, excess objects are destroyed via Clean. Does nothing if newAmount equals the current size.

Clean

GoodPool:Clean(
amountnumber?--

Number of objects to destroy. Defaults to all objects in the pool.

) → ()

Destroys objects in the pool via destroyFn.

If amount is provided, only that many objects are destroyed. Otherwise, the entire pool is cleared.

Objects that are currently in use (i.e. not yet returned) are not affected.

GetSize

GoodPool:GetSize() → number

Returns the number of objects currently sitting idle in the pool.

IsEmpty

GoodPool:IsEmpty() → boolean

Returns true if the pool has no objects available, false otherwise.

Return

GoodPool:Return(
itemT--

The object to return.

) → ()

Returns an object back to the pool so it can be reused later.

CAUTION

This does not reset the object's state. State reset is handled by initFn the next time the object is acquired via Get.

ReturnList

GoodPool:ReturnList(
list{T}--

The objects to return to the pool.

) → ()

Returns a list of objects back to the pool so they can be reused later.

CAUTION

This does not reset the objects' state. State reset is handled by initFn the next time each object is acquired via Get.

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Creates a new GoodPool.",
            "params": [
                {
                    "name": "createFn",
                    "desc": "Called when the pool is empty and a new object is needed.",
                    "lua_type": "() -> T"
                },
                {
                    "name": "initFn",
                    "desc": "Called every time an object is acquired. Use this to reset its state.",
                    "lua_type": "(T) -> ()"
                },
                {
                    "name": "destroyFn",
                    "desc": "Called on each object when `Clean` is invoked. Use this to free resources.",
                    "lua_type": "((T) -> ())?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "GoodPool<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 55,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "forInstance",
            "desc": "Creates a GoodPool that clones Instances from a template.\n\nIf a class name string is provided, a new Instance of that class is created\nand used as the template. The template is returned alongside the pool so you\ncan reference it later regardless of how it was created.\n```lua\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\n\nlocal partPool, template = GoodPool.forInstance(\n\tReplicatedStorage.Part,\n\tfunction(part)\n\t\tpart.Transparency = 0\n\t\tpart.Position = Vector3.new(0, 0, 0)\n\tend\n)\n\nprint(template == ReplicatedStorage.Part) -- true\n\nlocal part = partPool:Get()\npart.Parent = workspace\n\npartPool:Return(part)\n```",
            "params": [
                {
                    "name": "templateOrClassName",
                    "desc": "An existing Instance to clone, or a class name string to create one from.",
                    "lua_type": "Instance | string"
                },
                {
                    "name": "setupFn",
                    "desc": "Called every time an Instance is acquired. Use this to reset its state.",
                    "lua_type": "(Instance) -> ()"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "GoodPool<Instance>, Instance"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 97,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "Get",
            "desc": "Retrieves an object from the pool, passing it through `initFn` before returning.\n\nIf the pool is empty, a new object is created via `createFn`.",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 137,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "Preload",
            "desc": "Pre-fills the pool with a given number of objects created via `createFn`.\n\nUseful for avoiding lag spikes on first use. Does nothing if `amount` is <= 0.",
            "params": [
                {
                    "name": "amount",
                    "desc": "Number of objects to pre-fill the pool with.",
                    "lua_type": "number"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 151,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "Resize",
            "desc": "Resizes the pool to the given amount.\n\nIf `newAmount` is greater than the current size, new objects are created via `Preload`.\nIf `newAmount` is less, excess objects are destroyed via `Clean`.\nDoes nothing if `newAmount` equals the current size.",
            "params": [
                {
                    "name": "newAmount",
                    "desc": "The desired pool size.",
                    "lua_type": "number"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 172,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "Clean",
            "desc": "Destroys objects in the pool via `destroyFn`.\n\nIf `amount` is provided, only that many objects are destroyed.\nOtherwise, the entire pool is cleared.\n\nObjects that are currently in use (i.e. not yet returned) are not affected.",
            "params": [
                {
                    "name": "amount",
                    "desc": "Number of objects to destroy. Defaults to all objects in the pool.",
                    "lua_type": "number?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 197,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "GetSize",
            "desc": "Returns the number of objects currently sitting idle in the pool.",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 213,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "IsEmpty",
            "desc": "Returns `true` if the pool has no objects available, `false` otherwise.",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 223,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "Return",
            "desc": "Returns an object back to the pool so it can be reused later.\n\n:::caution\nThis does not reset the object's state. State reset is handled by\n`initFn` the next time the object is acquired via `Get`.\n:::",
            "params": [
                {
                    "name": "item",
                    "desc": "The object to return.",
                    "lua_type": "T"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 238,
                "path": "lib/init.luau"
            }
        },
        {
            "name": "ReturnList",
            "desc": "Returns a list of objects back to the pool so they can be reused later.\n\n:::caution\nThis does not reset the objects' state. State reset is handled by\n`initFn` the next time each object is acquired via `Get`.\n:::",
            "params": [
                {
                    "name": "list",
                    "desc": "The objects to return to the pool.",
                    "lua_type": "{T}"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 254,
                "path": "lib/init.luau"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "GoodPool",
    "desc": "A flexible and lightweight generic object pool.\n\nGoodPool allows you to reuse objects instead of repeatedly creating\nand destroying them. You provide a function to create the object,\nanother to initialize it when acquired, and an optional one to\ndestroy it when the pool is cleaned.\n```lua\nlocal tblPool = GoodPool.new(\n\tfunction()\n\t\treturn { value = 10 }\n\tend,\n\tfunction(tbl)\n\t\ttbl.value = 10\n\tend\n)\n\nlocal obj = tblPool:Get()\nobj.value += 10\nprint(obj.value) -- 20\n\ntblPool:Return(obj)\nprint(tblPool:Get().value) -- 10\n```",
    "source": {
        "line": 27,
        "path": "lib/init.luau"
    }
}