Add a generic cache system as gears.cache

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-06-13 16:43:05 +02:00
parent 9835f73a01
commit 42c913332f
3 changed files with 114 additions and 0 deletions

52
lib/gears/cache.lua Normal file
View File

@ -0,0 +1,52 @@
---------------------------------------------------------------------------
-- @author Uli Schlachter
-- @copyright 2015 Uli Schlachter
-- @release @AWESOME_VERSION@
-- @classmod gears.cache
---------------------------------------------------------------------------
local select = select
local setmetatable = setmetatable
local unpack = unpack or table.unpack
local cache = {}
--- Get an entry from the cache, creating it if it's missing.
-- @param ... Arguments for the creation callback. These are checked against the
-- cache contents for equality.
-- @return The entry from the cache
function cache:get(...)
local result = self._cache
for i = 1, select("#", ...) do
local arg = select(i, ...)
local next = result[arg]
if not next then
next = {}
result[arg] = next
end
result = next
end
local ret = result._entry
if not ret then
ret = { self._creation_cb(...) }
result._entry = ret
end
return unpack(ret)
end
--- Create a new cache object. A cache keeps some data that can be
-- garbage-collected at any time, but might be useful to keep.
-- @param creation_cb Callback that is used for creating missing cache entries.
-- @return A new cache object.
function cache.new(creation_cb)
return setmetatable({
_cache = setmetatable({}, { __mode = "v" }),
_creation_cb = creation_cb
}, {
__index = cache
})
end
return setmetatable(cache, { __call = function(_, ...) return cache.new(...) end })
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -15,6 +15,7 @@ return
surface = require("gears.surface"); surface = require("gears.surface");
wallpaper = require("gears.wallpaper"); wallpaper = require("gears.wallpaper");
timer = require("gears.timer"); timer = require("gears.timer");
cache = require("gears.cache");
} }
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

61
spec/gears/cache_spec.lua Normal file
View File

@ -0,0 +1,61 @@
---------------------------------------------------------------------------
-- @author Uli Schlachter
-- @copyright 2015 Uli Schlachter
---------------------------------------------------------------------------
local cache = require("gears.cache")
describe("gears.cache", function()
-- Make sure no cache is cleared during the tests
before_each(function()
collectgarbage("stop")
end)
after_each(function()
collectgarbage("restart")
end)
describe("Zero arguments", function()
it("Creation cb is called", function()
local called = false
local c = cache(function()
called = true
end)
local res = c:get()
assert.is_nil(res)
assert.is_true(called)
end)
end)
describe("Two arguments", function()
it("Cache works", function()
local num_calls = 0
local c = cache(function(a, b)
num_calls = num_calls + 1
return a + b
end)
local res1 = c:get(1, 2)
local res2 = c:get(1, 3)
local res3 = c:get(1, 2)
assert.is.equal(res1, 3)
assert.is.equal(res2, 4)
assert.is.equal(res3, 3)
assert.is.equal(num_calls, 2)
end)
it("Cache invalidation works", function()
local num_calls = 0
local c = cache(function(a, b)
num_calls = num_calls + 1
return a + b
end)
local res1 = c:get(1, 2)
collectgarbage("collect")
local res2 = c:get(1, 2)
assert.is.equal(res1, 3)
assert.is.equal(res2, 3)
assert.is.equal(num_calls, 2)
end)
end)
end)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80