Add a generic cache system as gears.cache
Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
9835f73a01
commit
42c913332f
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue