simple idpools module

This commit is contained in:
BlackMATov
2024-11-22 08:56:27 +07:00
parent 8b841d9ccc
commit 304c581005
5 changed files with 158 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
{
"recommendations": [
"sumneko.lua"
"sumneko.lua",
"tomblind.local-lua-debugger-vscode"
]
}

View File

@@ -1 +1 @@
local evo = require 'evolved.evolved'
require 'develop.untests.idpools_untests'

View File

@@ -0,0 +1,85 @@
local evo = require 'evolved.evolved'
do
local p1 = evo.idpools.idpool()
local p2 = evo.idpools.idpool()
assert(p1 ~= p2)
end
do
local p = evo.idpools.idpool()
local i1_1 = evo.idpools.acquire_id(p)
assert(i1_1 == 0x100001)
local i2_1 = evo.idpools.acquire_id(p)
assert(i2_1 == 0x100002)
do
local i, v = evo.idpools.unpack_id(i1_1)
assert(i == 1 and v == 1)
end
do
local i, v = evo.idpools.unpack_id(i2_1)
assert(i == 2 and v == 1)
end
end
do
local p = evo.idpools.idpool()
local i1_1 = evo.idpools.acquire_id(p)
local i2_1 = evo.idpools.acquire_id(p)
assert(evo.idpools.is_id_alive(p, i1_1))
assert(evo.idpools.is_id_alive(p, i2_1))
evo.idpools.release_id(p, i1_1)
assert(not evo.idpools.is_id_alive(p, i1_1))
assert(evo.idpools.is_id_alive(p, i2_1))
evo.idpools.release_id(p, i2_1)
assert(not evo.idpools.is_id_alive(p, i1_1))
assert(not evo.idpools.is_id_alive(p, i2_1))
local i2_2 = evo.idpools.acquire_id(p)
assert(i2_2 == 0x200002)
local i1_2 = evo.idpools.acquire_id(p)
assert(i1_2 == 0x200001)
assert(not evo.idpools.is_id_alive(p, i1_1))
assert(not evo.idpools.is_id_alive(p, i2_1))
assert(evo.idpools.is_id_alive(p, i1_2))
assert(evo.idpools.is_id_alive(p, i2_2))
end
do
local p = evo.idpools.idpool()
for _ = 1, 0xFFFFF - 1 do
_ = evo.idpools.acquire_id(p)
end
assert(evo.idpools.acquire_id(p) == 0x1FFFFF)
if not os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") then
assert(not pcall(evo.idpools.acquire_id, p))
end
end
do
local p = evo.idpools.idpool()
for _ = 1, 0x7FF - 1 do
evo.idpools.release_id(p, evo.idpools.acquire_id(p))
end
local i1_7FF = evo.idpools.acquire_id(p)
assert(i1_7FF == 0x7FF00001)
evo.idpools.release_id(p, i1_7FF)
local i1_1 = evo.idpools.acquire_id(p)
assert(i1_1 == 0x100001)
evo.idpools.release_id(p, i1_1)
end

View File

@@ -1,4 +1,5 @@
return {
idpools = require 'evolved.idpools',
registry = require 'evolved.registry',
singles = require 'evolved.singles',
vectors = require 'evolved.vectors',

69
evolved/idpools.lua Normal file
View File

@@ -0,0 +1,69 @@
local bit = require 'bit'
---@class evolved.idpools
local idpools = {}
---@class evolved.idpool
---@field acquired_ids integer[]
---@field available_index integer
local evolved_idpool_mt = {}
evolved_idpool_mt.__index = evolved_idpool_mt
---@return evolved.idpool
function idpools.idpool()
---@type evolved.idpool
local self = {
acquired_ids = {},
available_index = 0,
}
return setmetatable(self, evolved_idpool_mt)
end
---@param id integer
---@return integer index
---@return integer version
function idpools.unpack_id(id)
return bit.band(id, 0xFFFFF), bit.rshift(id, 20)
end
---@param idpool evolved.idpool
---@return integer
---@nodiscard
function idpools.acquire_id(idpool)
if idpool.available_index ~= 0 then
local index = idpool.available_index
local version = bit.band(idpool.acquired_ids[index], 0x7FF00000)
idpool.available_index = bit.band(idpool.acquired_ids[index], 0xFFFFF)
idpool.acquired_ids[index] = index + version
return idpool.acquired_ids[index]
end
if #idpool.acquired_ids == 0xFFFFF then
error('id index overflow', 2)
end
local index, version = #idpool.acquired_ids + 1, 0x100000
idpool.acquired_ids[index] = index + version
return idpool.acquired_ids[index]
end
---@param idpool evolved.idpool
---@param id integer
function idpools.release_id(idpool, id)
local index = bit.band(id, 0xFFFFF)
local version = bit.band(id, 0x7FF00000)
version = version == 0x7FF00000 and 0x100000 or version + 0x100000
idpool.acquired_ids[index] = idpool.available_index + version
idpool.available_index = index
end
---@param idpool evolved.idpool
---@param id integer
---@return boolean
---@nodiscard
function idpools.is_id_alive(idpool, id)
local index = bit.band(id, 0xFFFFF)
return idpool.acquired_ids[index] == id
end
return idpools