Skip to content

Commit

Permalink
Cleanup variable naming and add more useful comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Brown committed Sep 29, 2021
1 parent fd6b098 commit c9f8611
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
27 changes: 16 additions & 11 deletions src/cachetools/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def wrapper(*args, **kwargs):

else:

_locks = {}
_key_level_locks = {}

def wrapper(*args, **kwargs):
k = key(*args, **kwargs)
Expand All @@ -42,13 +42,16 @@ def wrapper(*args, **kwargs):
return cache[k]
except KeyError:
pass # key not found
_lock = _locks.setdefault(k, RLock())
with _lock:
try: # Callers blocked on the argument-level-lock may retrieve the pre-computed value
v = cache[k]
_key_level_lock = _key_level_locks.setdefault(k, RLock())
# Only one caller may generate or retrieve a value for this key
with _key_level_lock:
try:
# In the case that this thread was blocked, retrieve and return the now computed value
return cache[k]
except KeyError:
# Otherwise compute it on this thread since the key is not in the cache
v = func(*args, **kwargs)
_locks.pop(k)
_key_level_locks.pop(k)
try:
return cache.setdefault(k, v)
except ValueError:
Expand Down Expand Up @@ -85,7 +88,7 @@ def wrapper(self, *args, **kwargs):
return v

else:
_locks = {}
_key_level_locks = {}

def wrapper(self, *args, **kwargs):
c = cache(self)
Expand All @@ -97,14 +100,16 @@ def wrapper(self, *args, **kwargs):
return c[k]
except KeyError:
pass
_lock = _locks.setdefault(k, RLock())
with _lock:
_key_level_lock = _key_level_locks.setdefault(k, RLock())
# Only one caller may generate or retrieve a value for this key
with _key_level_lock:
try:
# In the case that this thread was blocked, retrieve and return the now computed value
return c[k]
except KeyError:
# Otherwise compute it on this thread since the key is not in the cache
v = method(self, *args, **kwargs)
_locks.pop(k)
# in case of a race, prefer the item already in the cache
_key_level_locks.pop(k)
try:
return c.setdefault(k, v)
except ValueError:
Expand Down
13 changes: 8 additions & 5 deletions src/cachetools/func.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _cache(cache, typed):
def decorator(func):
key = keys.typedkey if typed else keys.hashkey
lock = RLock()
locks = {}
key_level_locks = {}
stats = [0, 0]

def wrapper(*args, **kwargs):
Expand All @@ -64,13 +64,16 @@ def wrapper(*args, **kwargs):
return v
except KeyError:
stats[1] += 1
_lock = locks.setdefault(k, RLock())
with _lock:
try: # Callers blocked on the argument-level-lock may retrieve the pre-computed value
_key_level_lock = key_level_locks.setdefault(k, RLock())
# Only one caller may generate or retrieve a value for this key
with _key_level_lock:
try:
# In the case that this thread was blocked, retrieve and return the now computed value
return cache[k]
except KeyError:
# Otherwise compute it on this thread since the key is not in the cache
v = func(*args, **kwargs)
locks.pop(k)
key_level_locks.pop(k)
try:
return cache.setdefault(k,v)
except ValueError:
Expand Down

0 comments on commit c9f8611

Please sign in to comment.