util/cache.lua
author Kim Alvefur <zash@zash.se>
Sat, 23 Mar 2024 20:48:19 +0100
changeset 13465 c673ff1075bd
parent 13179 bbdaa770b955
permissions -rw-r--r--
mod_posix: Move everything to util.startup This allows greater control over the order of events. Notably, the internal ordering between daemonization, initialization of libunbound and setup of signal handling is sensitive. libunbound starts a separate thread for processing DNS requests. If this thread is started before signal handling has been set up, it will not inherit the signal handlers and instead behave as it would have before signal handlers were set up, i.e. cause the whole process to immediately exit. libunbound is usually initialized on the first DNS request, usually triggered by an outgoing s2s connection attempt. If daemonization happens before signals have been set up, signals may not be processed at all.
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
}