Code

Opened 9 years ago

Closed 9 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: UI/UX:

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()
     #   

Attachments (0)

Change History (2)

comment:1 Changed 9 years ago by adrian

  • Summary changed from Make simle cache thread-safe to Make simple cache thread-safe

comment:2 Changed 9 years ago by jacob

  • Resolution set to fixed
  • Status changed from new to closed

The new locmem backend is threadsafe; see [686]

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.