~brook/bzr-cvsps-import/fix-402690-788914-788915

« back to all changes in this revision

Viewing changes to cvsps/lru_cache.py

  • Committer: John Arbash Meinel
  • Date: 2007-01-19 18:04:37 UTC
  • Revision ID: john@arbash-meinel.com-20070119180437-12un9b2wea0jgokm
Handle when replacing a key that already exists

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
        :param cleanup: None or a function taking (key, value) to indicate
54
54
                        'value' sohuld be cleaned up.
55
55
        """
 
56
        if key in self._cache:
 
57
            self._remove(key)
56
58
        self._cache[key] = value
57
59
        self._cleanup[key] = cleanup
58
60
        self._record_access(key)
69
71
 
70
72
        # Make sure the cache is shrunk to the correct size
71
73
        while len(self._cache) > self._max_cache:
72
 
            k = self._queue.popleft()
73
 
            self._refcount[k] -= 1
74
 
            if not self._refcount[k]:
75
 
                del self._refcount[k]
76
 
                cleanup = self._cleanup.pop(k)
77
 
                val = self._cache.pop(k)
78
 
                if cleanup is not None:
79
 
                    cleanup(k, val)
80
 
                del cleanup
81
 
                del val
 
74
            self._remove_lru()
82
75
 
83
76
        # If our access queue is too large, clean it up too
84
77
        if len(self._queue) > 4*self._max_cache:
98
91
                len(self._refcount) == sum(self._refcount.itervalues()))
99
92
        gc.collect()
100
93
 
 
94
    def _remove(self, key):
 
95
        """Remove an entry, making sure to maintain the invariants."""
 
96
        cleanup = self._cleanup.pop(key)
 
97
        val = self._cache.pop(key)
 
98
        if cleanup is not None:
 
99
            cleanup(key, val)
 
100
        del cleanup
 
101
        del val
 
102
 
 
103
    def _remove_lru(self):
 
104
        """Remove one entry from the lru, and handle consequences.
 
105
 
 
106
        If there are no more references to the lru, then this entry should be
 
107
        removed from the cache.
 
108
        """
 
109
        key = self._queue.popleft()
 
110
        self._refcount[key] -= 1
 
111
        if not self._refcount[key]:
 
112
            del self._refcount[key]
 
113
            self._remove(key)
 
114
 
101
115
    def clear(self):
102
116
        """Clear out all of the cache."""
103
117
        # Clean up in LRU order
104
118
        while self._cache:
105
 
            k = self._queue.popleft()
106
 
            self._refcount[k] -= 1
107
 
            if not self._refcount[k]:
108
 
                del self._refcount[k]
109
 
                cleanup = self._cleanup.pop(k)
110
 
                val = self._cache.pop(k)
111
 
                if cleanup is not None:
112
 
                    cleanup(k, val)
113
 
                del cleanup
114
 
                del val
 
119
            self._remove_lru()