util/cache.lua
author Matthew Wild <mwild1@gmail.com>
Wed, 27 Mar 2024 15:39:03 +0000
changeset 13470 5d9ec2e55d74
parent 13179 bbdaa770b955
permissions -rw-r--r--
Merge 0.12->trunk
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local function _remove(list, m)
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
	if m.prev then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     4
		m.prev.next = m.next;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     5
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
	if m.next then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
		m.next.prev = m.prev;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
	end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
     9
	if list._tail == m then
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    10
		list._tail = m.prev;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    11
	end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    12
	if list._head == m then
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    13
		list._head = m.next;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    14
	end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    15
	list._count = list._count - 1;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    16
end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
local function _insert(list, m)
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    19
	if list._head then
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    20
		list._head.prev = m;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
	end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    22
	m.prev, m.next = nil, list._head;
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    23
	list._head = m;
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    24
	if not list._tail then
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    25
		list._tail = m;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
	end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    27
	list._count = list._count + 1;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    30
local cache_methods = {};
11202
c4c06fbb7d87 util.cache: Add __name to metatable
Matthew Wild <mwild1@gmail.com>
parents: 8401
diff changeset
    31
local cache_mt = { __name = "cache", __index = cache_methods };
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    32
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
function cache_methods:set(k, v)
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    34
	local m = self._data[k];
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    35
	if m then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    36
		-- Key already exists
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
		if v ~= nil then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
			-- Bump to head of list
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
			_remove(self, m);
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    40
			_insert(self, m);
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
			m.value = v;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
		else
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
			-- Remove from list
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
			_remove(self, m);
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    45
			self._data[k] = nil;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
		end
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    47
		return true;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
	-- New key
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
	if v == nil then
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    51
		return true;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
	-- Check whether we need to remove oldest k/v
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    54
	if self._count == self.size then
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    55
		local tail = self._tail;
7293
70ab13e81cf5 util.cache: Change behaviour of on_evict (and tests). Now accepts false instead of a function (never evict), or on_evict can return false to prevent eviction.
Matthew Wild <mwild1@gmail.com>
parents: 7292
diff changeset
    56
		local on_evict, evicted_key, evicted_value = self._on_evict, tail.key, tail.value;
13178
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    57
13179
bbdaa770b955 util.cache: Pass cache itself to eviction callback
Kim Alvefur <zash@zash.se>
parents: 13178
diff changeset
    58
		local do_evict = on_evict and on_evict(evicted_key, evicted_value, self);
13178
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    59
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    60
		if do_evict == false then
7293
70ab13e81cf5 util.cache: Change behaviour of on_evict (and tests). Now accepts false instead of a function (never evict), or on_evict can return false to prevent eviction.
Matthew Wild <mwild1@gmail.com>
parents: 7292
diff changeset
    61
			-- Cache is full, and we're not allowed to evict
70ab13e81cf5 util.cache: Change behaviour of on_evict (and tests). Now accepts false instead of a function (never evict), or on_evict can return false to prevent eviction.
Matthew Wild <mwild1@gmail.com>
parents: 7292
diff changeset
    62
			return false;
13178
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    63
		elseif self._count == self.size then
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    64
			-- Cache wasn't grown
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    65
			_remove(self, tail);
8ec7b7d6556f util.cache: Keep eviction candidate if callback resized to make room
Kim Alvefur <zash@zash.se>
parents: 11202
diff changeset
    66
			self._data[evicted_key] = nil;
7293
70ab13e81cf5 util.cache: Change behaviour of on_evict (and tests). Now accepts false instead of a function (never evict), or on_evict can return false to prevent eviction.
Matthew Wild <mwild1@gmail.com>
parents: 7292
diff changeset
    67
		end
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
	m = { key = k, value = v, prev = nil, next = nil };
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    71
	self._data[k] = m;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
	_insert(self, m);
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    73
	return true;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    74
end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    75
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    76
function cache_methods:get(k)
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    77
	local m = self._data[k];
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    78
	if m then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    79
		return m.value;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
	return nil;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    83
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    84
function cache_methods:items()
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
    85
	local m = self._head;
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    86
	return function ()
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    87
		if not m then
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    88
			return;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    89
		end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    90
		local k, v = m.key, m.value;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    91
		m = m.next;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    92
		return k, v;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    93
	end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    94
end
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    95
7357
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
    96
function cache_methods:values()
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
    97
	local m = self._head;
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
    98
	return function ()
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
    99
		if not m then
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   100
			return;
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   101
		end
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   102
		local v = m.value;
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   103
		m = m.next;
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   104
		return v;
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   105
	end
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   106
end
8ca7f1c2c660 util.cache: Add method for iterating over values
Kim Alvefur <zash@zash.se>
parents: 7293
diff changeset
   107
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   108
function cache_methods:count()
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   109
	return self._count;
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   110
end
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   111
7292
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   112
function cache_methods:head()
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   113
	local head = self._head;
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   114
	if not head then return nil, nil; end
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   115
	return head.key, head.value;
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   116
end
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   117
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   118
function cache_methods:tail()
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   119
	local tail = self._tail;
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   120
	if not tail then return nil, nil; end
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   121
	return tail.key, tail.value;
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   122
end
42e7545d5ae3 util.cache: Add head() and tail() methods (and tests)
Matthew Wild <mwild1@gmail.com>
parents: 7019
diff changeset
   123
8400
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   124
function cache_methods:resize(new_size)
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   125
	new_size = assert(tonumber(new_size), "cache size must be a number");
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   126
	new_size = math.floor(new_size);
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   127
	assert(new_size > 0, "cache size must be greater than zero");
8401
3eff1b60269a util.cache: Call on-eviction callback when shrinking
Kim Alvefur <zash@zash.se>
parents: 8400
diff changeset
   128
	local on_evict = self._on_evict;
8400
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   129
	while self._count > new_size do
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   130
		local tail = self._tail;
8401
3eff1b60269a util.cache: Call on-eviction callback when shrinking
Kim Alvefur <zash@zash.se>
parents: 8400
diff changeset
   131
		local evicted_key, evicted_value = tail.key, tail.value;
13179
bbdaa770b955 util.cache: Pass cache itself to eviction callback
Kim Alvefur <zash@zash.se>
parents: 13178
diff changeset
   132
		if on_evict ~= nil and (on_evict == false or on_evict(evicted_key, evicted_value, self) == false) then
8401
3eff1b60269a util.cache: Call on-eviction callback when shrinking
Kim Alvefur <zash@zash.se>
parents: 8400
diff changeset
   133
			-- Cache is full, and we're not allowed to evict
3eff1b60269a util.cache: Call on-eviction callback when shrinking
Kim Alvefur <zash@zash.se>
parents: 8400
diff changeset
   134
			return false;
3eff1b60269a util.cache: Call on-eviction callback when shrinking
Kim Alvefur <zash@zash.se>
parents: 8400
diff changeset
   135
		end
8400
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   136
		_remove(self, tail);
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   137
		self._data[evicted_key] = nil;
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   138
	end
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   139
	self.size = new_size;
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   140
	return true;
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   141
end
99d85731e3ee util.cache: Add a method to resize the cache
Kim Alvefur <zash@zash.se>
parents: 8399
diff changeset
   142
7438
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   143
function cache_methods:table()
7705
9385c367e920 util.cache: Ignore unused argument [luacheck]
Kim Alvefur <zash@zash.se>
parents: 7438
diff changeset
   144
	--luacheck: ignore 212/t
7438
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   145
	if not self.proxy_table then
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   146
		self.proxy_table = setmetatable({}, {
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   147
			__index = function (t, k)
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   148
				return self:get(k);
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   149
			end;
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   150
			__newindex = function (t, k, v)
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   151
				if not self:set(k, v) then
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   152
					error("failed to insert key into cache - full");
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   153
				end
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   154
			end;
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   155
			__pairs = function (t)
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   156
				return self:items();
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   157
			end;
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   158
			__len = function (t)
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   159
				return self:count();
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   160
			end;
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   161
		});
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   162
	end
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   163
	return self.proxy_table;
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   164
end
8603b16e85c7 util.cache: Add support for creating a proxy table to a cache, that looks and acts (mostly) like a normal table. No tests yet.
Matthew Wild <mwild1@gmail.com>
parents: 7357
diff changeset
   165
8399
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   166
function cache_methods:clear()
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   167
	self._data = {};
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   168
	self._count = 0;
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   169
	self._head = nil;
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   170
	self._tail = nil;
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   171
end
fbe1f99fb245 util.cache: Add method for removing all data (does not call eviction callback)
Kim Alvefur <zash@zash.se>
parents: 7705
diff changeset
   172
6948
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   173
local function new(size, on_evict)
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   174
	size = assert(tonumber(size), "cache size must be a number");
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   175
	size = math.floor(size);
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   176
	assert(size > 0, "cache size must be greater than zero");
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   177
	local data = {};
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   178
	return setmetatable({ _data = data, _count = 0, size = size, _head = nil, _tail = nil, _on_evict = on_evict }, cache_mt);
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   179
end
d779c55058c6 util.cache: Small update to prefix private fields with an underscore, add a :count() method (same as util.queue) and add an optional on_evict callback
Matthew Wild <mwild1@gmail.com>
parents: 6946
diff changeset
   180
6936
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   181
return {
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   182
	new = new;
d636815d81c3 util.cache: Ordered key->value data structure, with size limit (same as pubsub)
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   183
}