1# -*- coding: utf-8 -*-
2''' pixbuf_cache.py - Caches book covers for the library display.'''
3
4from collections import OrderedDict
5from threading import Lock
6
7__all__ = ['get_pixbuf_cache']
8
9class _PixbufCache(object):
10
11    ''' Pixbuf cache for the library window. Instead of loading book covers
12    from disk again after switching collection or using filtering, this class
13    stores a pre-defined amount of pixbufs in memory, evicting older pixbufs
14    as necessary.
15    '''
16
17    def __init__(self, size):
18        #: Cache size, in images
19        assert size > 0
20        self.cachesize = size
21        #: Store book id => pixbuf
22        self._cache = OrderedDict()
23        #: Ensure thread safety
24        self._lock = Lock()
25
26    def add(self, path, pixbuf):
27        ''' Add a pixbuf to cache with path as key. '''
28        with self._lock:
29            if path in self._cache:
30                return
31            while len(self._cache) > self.cachesize:
32                self._cache.popitem(last=False)
33            self._cache[path] = pixbuf
34
35    def get(self, path):
36        ''' Return the pixbuf for the given cache path, or None if not exists. '''
37        with self._lock:
38            return self._cache.get(path, None)
39
40    def pop(self, path):
41        ''' Remove the object with the given cache path. '''
42        with self._lock:
43            self._cache.pop(path, None)
44
45    def clear(self):
46        ''' Clear all cached objects. '''
47        with self._lock:
48            self._cache.clear()
49
50
51_cache = None
52
53def get_pixbuf_cache():
54    global _cache
55
56    if _cache is None:
57        # 500 items is about 130 MB of RAM with 500px thumbnails,
58        # and about 35 MB at 250px.
59        _cache = _PixbufCache(500)
60    return _cache
61
62# vim: expandtab:sw=4:ts=4
63