8000 Fixed #23642 -- Made LocMemCache.incr() thread-safe as documented · alex-python/django@6448dd8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6448dd8

Browse files
tchaumenyloic
authored andcommitted
Fixed #23642 -- Made LocMemCache.incr() thread-safe as documented
1 parent c48a29a commit 6448dd8

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

django/core/cache/backends/locmem.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"Thread-safe in-memory cache backend."
22

3+
from contextlib import contextmanager
34
import time
45
try:
56
from django.utils.six.moves import cPickle as pickle
@@ -17,6 +18,12 @@
1718
_locks = {}
1819

1920

21+
@contextmanager
22+
def dummy():
23+
"""A context manager that does nothing special."""
24+
yield
25+
26+
2027
class LocMemCache(BaseCache):
2128
def __init__(self, name, params):
2229
BaseCache.__init__(self, params)
@@ -34,11 +41,11 @@ def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
3441
return True
3542
return False
3643

37-
def get(self, key, default=None, version=None):
44+
def get(self, key, default=None, version=None, acquire_lock=True):
3845
key = self.make_key(key, version=version)
3946
self.validate_key(key)
4047
pickled = None
41-
with self._lock.reader():
48+
with (self._lock.reader() if acquire_lock else dummy()):
4249
if not self._has_expired(key):
4350
pickled = self._cache[key]
4451
if pickled is not None:
@@ -47,7 +54,7 @@ def get(self, key, default=None, version=None):
4754
except pickle.PickleError:
4855
return default
4956

50-
with self._lock.writer():
57+
with (self._lock.writer() if acquire_lock else dummy()):
5158
try:
5259
del self._cache[key]
5360
del self._expire_info[key]
@@ -69,13 +76,13 @@ def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
6976
self._set(key, pickled, timeout)
7077

7178
def incr(self, key, delta=1, version=None):
72-
value = self.get(key, version=version)
73-
if value is None:
74-
raise ValueError("Key '%s' not found" % key)
75-
new_value = value + delta
76-
key = self.make_key(key, version=version)
77-
pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL)
7879
with self._lock.writer():
80+
value = self.get(key, version=version, acquire_lock=False)
81+
if value is None:
82+
raise ValueError("Key '%s' not found" % key)
83+
new_value = value + delta
84+
key = self.make_key(key, version=version)
85+
pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL)
7986
self._cache[key] = pickled
8087
return new_value
8188

docs/releases/1.8.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ Minor features
157157
Cache
158158
^^^^^
159159

160-
* ...
160+
* The ``incr()`` method of the
161+
``django.core.cache.backends.locmem.LocMemCache`` backend is now thread-safe.
161162

162163
Email
163164
^^^^^

0 commit comments

Comments
 (0)
0