Commit e4919f64 authored by Alex Gaynor's avatar Alex Gaynor
Browse files

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
parent 1086a9a8
Loading
Loading
Loading
Loading
+20 −40
Original line number Diff line number Diff line
"Thread-safe in-memory cache backend."

from __future__ import with_statement

import time
try:
    import cPickle as pickle
@@ -26,8 +28,7 @@ class LocMemCache(BaseCache):
    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 @@ class LocMemCache(BaseCache):
                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 @@ class LocMemCache(BaseCache):
                    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 @@ class LocMemCache(BaseCache):
    def set(self, key, value, timeout=None, version=None):
        key = self.make_key(key, version=version)
        self.validate_key(key)
        self._lock.writer_enters()
        with self._lock.writer():
            try:
                pickled = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
                self._set(key, pickled, timeout)
            except pickle.PickleError:
                pass
        finally:
            self._lock.writer_leaves()

    def incr(self, key, delta=1, version=None):
        value = self.get(key, version=version)
@@ -93,39 +84,31 @@ class LocMemCache(BaseCache):
            raise ValueError("Key '%s' not found" % key)
        new_value = value + delta
        key = self.make_key(key, version=version)
        self._lock.writer_enters()
        with self._lock.writer():
            try:
                pickled = pickle.dumps(new_value, pickle.HIGHEST_PROTOCOL)
                self._cache[key] = pickled
            except pickle.PickleError:
                pass
        finally:
            self._lock.writer_leaves()
        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 @@ class LocMemCache(BaseCache):
    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()
+23 −15
Original line number Diff line number Diff line
@@ -6,12 +6,16 @@ Synchronization primitives:
(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 @@ class RWLock:
        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 @@ class RWLock:
                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