mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-02 10:56:06 -04:00
Add concept of cache contexts
This commit is contained in:
parent
5674ea3e6c
commit
4161ff2fc4
5 changed files with 278 additions and 20 deletions
|
@ -30,13 +30,14 @@ def enumerate_leaves(node, depth):
|
|||
|
||||
|
||||
class _Node(object):
|
||||
__slots__ = ["prev_node", "next_node", "key", "value"]
|
||||
__slots__ = ["prev_node", "next_node", "key", "value", "callbacks"]
|
||||
|
||||
def __init__(self, prev_node, next_node, key, value):
|
||||
def __init__(self, prev_node, next_node, key, value, callbacks=[]):
|
||||
self.prev_node = prev_node
|
||||
self.next_node = next_node
|
||||
self.key = key
|
||||
self.value = value
|
||||
self.callbacks = callbacks
|
||||
|
||||
|
||||
class LruCache(object):
|
||||
|
@ -44,6 +45,9 @@ class LruCache(object):
|
|||
Least-recently-used cache.
|
||||
Supports del_multi only if cache_type=TreeCache
|
||||
If cache_type=TreeCache, all keys must be tuples.
|
||||
|
||||
Can also set callbacks on objects when getting/setting which are fired
|
||||
when that key gets invalidated/evicted.
|
||||
"""
|
||||
def __init__(self, max_size, keylen=1, cache_type=dict):
|
||||
cache = cache_type()
|
||||
|
@ -62,10 +66,10 @@ class LruCache(object):
|
|||
|
||||
return inner
|
||||
|
||||
def add_node(key, value):
|
||||
def add_node(key, value, callbacks=[]):
|
||||
prev_node = list_root
|
||||
next_node = prev_node.next_node
|
||||
node = _Node(prev_node, next_node, key, value)
|
||||
node = _Node(prev_node, next_node, key, value, callbacks)
|
||||
prev_node.next_node = node
|
||||
next_node.prev_node = node
|
||||
cache[key] = node
|
||||
|
@ -88,23 +92,41 @@ class LruCache(object):
|
|||
prev_node.next_node = next_node
|
||||
next_node.prev_node = prev_node
|
||||
|
||||
for cb in node.callbacks:
|
||||
cb()
|
||||
node.callbacks = []
|
||||
|
||||
@synchronized
|
||||
def cache_get(key, default=None):
|
||||
def cache_get(key, default=None, callback=None):
|
||||
node = cache.get(key, None)
|
||||
if node is not None:
|
||||
move_node_to_front(node)
|
||||
if callback:
|
||||
node.callbacks.append(callback)
|
||||
return node.value
|
||||
else:
|
||||
return default
|
||||
|
||||
@synchronized
|
||||
def cache_set(key, value):
|
||||
def cache_set(key, value, callback=None):
|
||||
node = cache.get(key, None)
|
||||
if node is not None:
|
||||
if value != node.value:
|
||||
for cb in node.callbacks:
|
||||
cb()
|
||||
node.callbacks = []
|
||||
|
||||
if callback:
|
||||
node.callbacks.append(callback)
|
||||
|
||||
move_node_to_front(node)
|
||||
node.value = value
|
||||
else:
|
||||
add_node(key, value)
|
||||
if callback:
|
||||
callbacks = [callback]
|
||||
else:
|
||||
callbacks = []
|
||||
add_node(key, value, callbacks)
|
||||
if len(cache) > max_size:
|
||||
todelete = list_root.prev_node
|
||||
delete_node(todelete)
|
||||
|
@ -148,6 +170,9 @@ class LruCache(object):
|
|||
def cache_clear():
|
||||
list_root.next_node = list_root
|
||||
list_root.prev_node = list_root
|
||||
for node in cache.values():
|
||||
for cb in node.callbacks:
|
||||
cb()
|
||||
cache.clear()
|
||||
|
||||
@synchronized
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue