Changeset

13174:8ec7b7d6556f

util.cache: Keep eviction candidate if callback resized to make room Previously either the old or the new values would be rejected, even if the cache was resized to allow more items.
author Kim Alvefur <zash@zash.se>
date Fri, 30 Jun 2023 22:01:49 +0200
parents 13173:4906d4990ffe
children 13175:bbdaa770b955
files spec/util_cache_spec.lua util/cache.lua
diffstat 2 files changed, 29 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/spec/util_cache_spec.lua	Fri Jun 30 18:51:03 2023 +0200
+++ b/spec/util_cache_spec.lua	Fri Jun 30 22:01:49 2023 +0200
@@ -388,5 +388,26 @@
 			c:resize(3);
 			assert.same({"v5", "v4", "v3"}, vs(c));
 		end);
+
+		it("eviction stuff", function ()
+			local c;
+			c = cache.new(4, function(_k,_v)
+				if c.size < 10 then
+					c:resize(c.size*2);
+				end
+			end)
+			for i = 1,20 do
+				c:set(i,i)
+			end
+			assert.equal(16, c.size);
+			assert.is_nil(c:get(1))
+			assert.is_nil(c:get(4))
+			assert.equal(5, c:get(5))
+			assert.equal(20, c:get(20))
+			c:resize(4)
+			assert.equal(20, c:get(20))
+			assert.equal(17, c:get(17))
+			assert.is_nil(c:get(10))
+		end)
 	end);
 end);
--- a/util/cache.lua	Fri Jun 30 18:51:03 2023 +0200
+++ b/util/cache.lua	Fri Jun 30 22:01:49 2023 +0200
@@ -54,12 +54,17 @@
 	if self._count == self.size then
 		local tail = self._tail;
 		local on_evict, evicted_key, evicted_value = self._on_evict, tail.key, tail.value;
-		if on_evict ~= nil and (on_evict == false or on_evict(evicted_key, evicted_value) == false) then
+
+		local do_evict = on_evict and on_evict(evicted_key, evicted_value);
+
+		if do_evict == false then
 			-- Cache is full, and we're not allowed to evict
 			return false;
+		elseif self._count == self.size then
+			-- Cache wasn't grown
+			_remove(self, tail);
+			self._data[evicted_key] = nil;
 		end
-		_remove(self, tail);
-		self._data[evicted_key] = nil;
 	end
 
 	m = { key = k, value = v, prev = nil, next = nil };