mirror of
https://github.com/sbrl/Minetest-WorldEditAdditions.git
synced 2024-12-24 14:42:24 +01:00
Implement an LRU cache
This commit is contained in:
parent
e799a2ea61
commit
81957070f9
@ -13,6 +13,7 @@ worldeditadditions.Mesh,
|
|||||||
worldeditadditions.Face = dofile(worldeditadditions.modpath.."/utils/mesh.lua")
|
worldeditadditions.Face = dofile(worldeditadditions.modpath.."/utils/mesh.lua")
|
||||||
|
|
||||||
worldeditadditions.Queue = dofile(worldeditadditions.modpath.."/utils/queue.lua")
|
worldeditadditions.Queue = dofile(worldeditadditions.modpath.."/utils/queue.lua")
|
||||||
|
worldeditadditions.LRU = dofile(worldeditadditions.modpath.."/utils/lru.lua")
|
||||||
|
|
||||||
|
|
||||||
dofile(worldeditadditions.modpath.."/utils/strings/init.lua")
|
dofile(worldeditadditions.modpath.."/utils/strings/init.lua")
|
||||||
|
80
worldeditadditions/utils/lru.lua
Normal file
80
worldeditadditions/utils/lru.lua
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
local Queue
|
||||||
|
if worldeditadditions then
|
||||||
|
Queue = dofile(worldeditadditions.modpath.."/utils/queue.lua")
|
||||||
|
else
|
||||||
|
Queue = require("queue")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- A least-recently-used cache implementation.
|
||||||
|
-- @class
|
||||||
|
local LRU = {}
|
||||||
|
LRU.__index = LRU
|
||||||
|
|
||||||
|
--- Creates a new LRU cache.
|
||||||
|
-- Optimal sizes: 8, 16, 32, 64 or any value above
|
||||||
|
-- @param max_size=32 number The maximum number of items to store in the cache.
|
||||||
|
-- @returns LRU A new LRU cache.
|
||||||
|
function LRU.new(max_size)
|
||||||
|
if not max_size then max_size = 32 end
|
||||||
|
local result = {
|
||||||
|
max_size = max_size,
|
||||||
|
cache = { },
|
||||||
|
size = 0,
|
||||||
|
queue = Queue.new()
|
||||||
|
}
|
||||||
|
setmetatable(result, LRU)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Determines whether the given key is present in this cache object.
|
||||||
|
-- Does NOT update the most recently used status of said key.
|
||||||
|
-- @param key string The key to check.
|
||||||
|
-- @returns bool Whether the given key exists in the cache or not.
|
||||||
|
function LRU:has(key)
|
||||||
|
return self.cache[key] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets the value associated with the given key.
|
||||||
|
-- @param key string The key to retrieve the value for.
|
||||||
|
-- @returns any|nil The value associated with the given key, or nil if it doesn't exist in this cache.
|
||||||
|
function LRU:get(key)
|
||||||
|
if not self.cache[key] then return nil end
|
||||||
|
|
||||||
|
-- Put it to the end of the queue
|
||||||
|
self.queue:remove_index(self.cache[key].index)
|
||||||
|
self.cache[key].index = self.queue:enqueue(key)
|
||||||
|
|
||||||
|
return self.cache[key].value
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Adds a given key-value pair to this cache.
|
||||||
|
-- Note that this might (or might not) result in the eviction of another item.
|
||||||
|
-- @param key string The key of the item to add.
|
||||||
|
-- @param value any The value to associate with the given key.
|
||||||
|
-- @returns nil
|
||||||
|
function LRU:set(key, value)
|
||||||
|
if self.cache[key] ~= nil then
|
||||||
|
-- It's already present in the cache - update it
|
||||||
|
-- Put it to the end of the queue
|
||||||
|
self.queue:remove_index(self.cache[key].index)
|
||||||
|
local new_index = self.queue:enqueue(key)
|
||||||
|
-- Update the cache entry
|
||||||
|
self.cache[key] = {
|
||||||
|
value = value,
|
||||||
|
index = new_index
|
||||||
|
}
|
||||||
|
else
|
||||||
|
-- It's not in the cache -- add it
|
||||||
|
self.cache[key] = { value = value, index = self.queue:enqueue(key) }
|
||||||
|
|
||||||
|
self.size = self.size + 1
|
||||||
|
if self.size > self.max_size then
|
||||||
|
-- The cache is full, delete the oldest item
|
||||||
|
local oldest_key = self.queue:dequeue()
|
||||||
|
self.cache[oldest_key] = nil
|
||||||
|
self.size = self.size - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return LRU
|
@ -15,6 +15,7 @@ function Queue:enqueue(value)
|
|||||||
local new_last = self.last + 1
|
local new_last = self.last + 1
|
||||||
self.last = new_last
|
self.last = new_last
|
||||||
self.items[new_last] = value
|
self.items[new_last] = value
|
||||||
|
return new_last
|
||||||
end
|
end
|
||||||
|
|
||||||
function Queue:contains(value)
|
function Queue:contains(value)
|
||||||
@ -30,15 +31,25 @@ function Queue:is_empty()
|
|||||||
return self.first > self.last
|
return self.first > self.last
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Queue:remove_index(index)
|
||||||
|
self.items[index] = nil
|
||||||
|
end
|
||||||
|
|
||||||
function Queue:dequeue()
|
function Queue:dequeue()
|
||||||
local first = self.first
|
|
||||||
if Queue.is_empty(self) then
|
if Queue.is_empty(self) then
|
||||||
error("Error: The self is empty!")
|
error("Error: The self is empty!")
|
||||||
end
|
end
|
||||||
|
|
||||||
local value = self.items[first]
|
local first = self.first
|
||||||
self.items[first] = nil -- Help the garbage collector out
|
-- Find the next non-nil item
|
||||||
self.first = first + 1
|
local value
|
||||||
|
while value == nil do
|
||||||
|
if first >= self.last then return nil end
|
||||||
|
value = self.items[first]
|
||||||
|
self.items[first] = nil -- Help the garbage collector out
|
||||||
|
first = first + 1
|
||||||
|
end
|
||||||
|
self.first = first
|
||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user