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");
|
||||
wallpaper = require("gears.wallpaper");
|
||||
timer = require("gears.timer");
|
||||
cache = require("gears.cache");
|
||||
}
|
||||
|
||||
-- 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