Opened 19 years ago

Closed 19 years ago

#234 closed defect (fixed)

Make simple cache thread-safe

Reported by: nesh <nesh [at] studioquattro [dot] co [dot] yu> Owned by: Jacob
Component: Core (Cache system) Version:
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Proposition for thread-safe SimpleCache:

It's not tested, just a example.

import time
from threading import Lock

_cache = None
_expire_info = None
_max_entries = None
_cull_frequency = None

class _SimpleCache(_Cache):
    def __init__(self, host, params):
        _Cache.__init__(self, params)

        self._lock = Lock()
        
        if _cache is None: # ignore if cache is initialised
            _cache = {}
            _expire_info = {}
            max_entries = params.get('max_entries', 300)
            try:
                _max_entries = int(max_entries)
            except (ValueError, TypeError):
                _max_entries = 300
                
            cull_frequency = params.get('cull_frequency', 3)
            try:
                _cull_frequency = int(cull_frequency)
            except (ValueError, TypeError):
                _cull_frequency = 3
        #
    #
        
    def get(self, key, default=None):
        self._lock.acquire()
        try:
            now = time.time()
            exp = self._expire_info.get(key, now)
            if exp is not None and exp < now:
                del self._cache[key]
                del self._expire_info[key]
                return default
            else:
                return self._cache.get(key, default)
        finally:
            self._lock.release()
    #
        
    def set(self, key, value, timeout=None):
        self._lock.acquire()
        try:
            if len(self._cache) >= self._max_entries:
                self._cull()
            if timeout is None:
                timeout = self.default_timeout
            self._cache[key] = value
            self._expire_info[key] = time.time() + timeout
        finally:
            self._lock.release()
    #
        
    def delete(self, key):
        self._lock.acquire()
        try:
            try:
                del self._cache[key]
            except KeyError:
                pass
            try:
                del self._expire_info[key]
            except KeyError:
                pass
        finally:
            self._lock.release()
    #
            
    def has_key(self, key):
        return self._cache.has_key(key)

    def _cull(self):
        self._lock.acquire()
        try:
            if self._cull_frequency == 0:
                self._cache.clear()
                self._expire_info.clear()
            else:
                doomed = [k for (i, k) in enumerate(self._cache) if i % self._cull_frequency == 0]
                for k in doomed:
                    self.delete(k)
        finally:
            self._lock.release()
     #   

Change History (2)

comment:1 by Adrian Holovaty, 19 years ago

Summary: Make simle cache thread-safeMake simple cache thread-safe

comment:2 by Jacob, 19 years ago

Resolution: fixed
Status: newclosed

The new locmem backend is threadsafe; see [686]

Note: See TracTickets for help on using tickets.
Back to Top