From e4919f64b09a1813d5f1b4854f8b7c6e3a3c7a9a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 27 Nov 2011 04:28:31 +0000 Subject: [PATCH] Clean up the the locmem cache backend and utils.synch by using context managers. Puch prettier. git-svn-id: http://code.djangoproject.com/svn/django/trunk@17152 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/cache/backends/locmem.py | 60 ++++++++++------------------ django/utils/synch.py | 38 +++++++++++------- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/django/core/cache/backends/locmem.py b/django/core/cache/backends/locmem.py index 59293527b7d46..6ba0c98945e90 100644 --- a/django/core/cache/backends/locmem.py +++ b/django/core/cache/backends/locmem.py @@ -1,5 +1,7 @@ "Thread-safe in-memory cache backend." +from __future__ import with_statement + import time try: import cPickle as pickle @@ -26,8 +28,7 @@ def __init__(self, name, params): def add(self, key, value, timeout=None, version=None): key = self.make_key(key, version=version) self.validate_key(key) - self._lock.writer_enters() - try: + with self._lock.writer(): exp = self._expire_info.get(key) if exp is None or exp <= time.time(): try: @@ -37,14 +38,11 @@ def add(self, key, value, timeout=None, version=None): except pickle.PickleError: pass return False - finally: - self._lock.writer_leaves() def get(self, key, default=None, version=None): key = self.make_key(key, version=version) self.validate_key(key) - self._lock.reader_enters() - try: + with self._lock.reader(): exp = self._expire_info.get(key) if exp is None: return default @@ -54,18 +52,13 @@ def get(self, key, default=None, version=None): return pickle.loads(pickled) except pickle.PickleError: return default - finally: - self._lock.reader_leaves() - self._lock.writer_enters() - try: + with self._lock.writer(): try: del self._cache[key] del self._expire_info[key] except KeyError: pass return default - finally: - self._lock.writer_leaves() def _set(self, key, value, timeout=None): if len(self._cache) >= self._max_entries: @@ -78,14 +71,12 @@ def _set(self, key, value, timeout=None): def set(self, key, value, timeout=None, version=None): key = self.make_key(key, version=version) self.validate_key(key) - self._lock.writer_enters() - try: - pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) - self._set(key, pickled, timeout) - except pickle.PickleError: - pass - finally: - self._lock.writer_leaves() + with self._lock.writer(): + try: + pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL) + self._set(key, pickled, timeout) + except pickle.PickleError: + pass def incr(self, key, delta=1, version=None): value = self.get(key, version=version) @@ -93,39 +84,31 @@ def incr(self, key, delta=1, version=None): raise ValueError("Key '%s' not found" % key) new_value = value + delta key = self.make_key(key, version=version) - self._lock.writer_enters() - try: - pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL) - self._cache[key] = pickled - except pickle.PickleError: - pass - finally: - self._lock.writer_leaves() + with self._lock.writer(): + try: + pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL) + self._cache[key] = pickled + except pickle.PickleError: + pass return new_value def has_key(self, key, version=None): key = self.make_key(key, version=version) self.validate_key(key) - self._lock.reader_enters() - try: + with self._lock.reader(): exp = self._expire_info.get(key) if exp is None: return False elif exp > time.time(): return True - finally: - self._lock.reader_leaves() - self._lock.writer_enters() - try: + with self._lock.writer(): try: del self._cache[key] del self._expire_info[key] except KeyError: pass return False - finally: - self._lock.writer_leaves() def _cull(self): if self._cull_frequency == 0: @@ -148,11 +131,8 @@ def _delete(self, key): def delete(self, key, version=None): key = self.make_key(key, version=version) self.validate_key(key) - self._lock.writer_enters() - try: + with self._lock.writer(): self._delete(key) - finally: - self._lock.writer_leaves() def clear(self): self._cache.clear() diff --git a/django/utils/synch.py b/django/utils/synch.py index 2e808c1e01d7a..d6ae2f0a72d70 100644 --- a/django/utils/synch.py +++ b/django/utils/synch.py @@ -6,12 +6,16 @@ (Contributed to Django by eugene@lazutkin.com) """ +from __future__ import with_statement + +import contextlib try: import threading except ImportError: import dummy_threading as threading -class RWLock: + +class RWLock(object): """ Classic implementation of reader-writer lock with preference to writers. @@ -34,43 +38,41 @@ def __init__(self): self.waiting_writers = 0 def reader_enters(self): - self.mutex.acquire() - try: + with self.mutex: if self.active_writers == 0 and self.waiting_writers == 0: self.active_readers += 1 self.can_read.release() else: self.waiting_readers += 1 - finally: - self.mutex.release() self.can_read.acquire() def reader_leaves(self): - self.mutex.acquire() - try: + with self.mutex: self.active_readers -= 1 if self.active_readers == 0 and self.waiting_writers != 0: self.active_writers += 1 self.waiting_writers -= 1 self.can_write.release() + + @contextlib.contextmanager + def reader(self): + self.reader_enters() + try: + yield finally: - self.mutex.release() + self.reader_leaves() def writer_enters(self): - self.mutex.acquire() - try: + with self.mutex: if self.active_writers == 0 and self.waiting_writers == 0 and self.active_readers == 0: self.active_writers += 1 self.can_write.release() else: self.waiting_writers += 1 - finally: - self.mutex.release() self.can_write.acquire() def writer_leaves(self): - self.mutex.acquire() - try: + with self.mutex: self.active_writers -= 1 if self.waiting_writers != 0: self.active_writers += 1 @@ -83,5 +85,11 @@ def writer_leaves(self): while t > 0: self.can_read.release() t -= 1 + + @contextlib.contextmanager + def writer(self): + self.writer_enters() + try: + yield finally: - self.mutex.release() + self.writer_leaves() \ No newline at end of file