1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkLruImageCache_DEFINED
9#define SkLruImageCache_DEFINED
10
11#include "SkImageCache.h"
12#include "SkThread.h"
13#include "SkTInternalLList.h"
14
15class CachedPixels;
16
17/**
18 *  SkImageCache implementation that uses an LRU cache to age out old images.
19 */
20class SkLruImageCache : public SkImageCache {
21
22public:
23    SK_DECLARE_INST_COUNT(SkLruImageCache)
24
25    SkLruImageCache(size_t budget);
26
27    virtual ~SkLruImageCache();
28
29#ifdef SK_DEBUG
30    virtual MemoryStatus getMemoryStatus(ID) const SK_OVERRIDE;
31    virtual void purgeAllUnpinnedCaches() SK_OVERRIDE;
32#endif
33
34    /**
35     *  Set the byte limit on cached pixels. If more bytes are used than this, the cache will free
36     *  unpinned memory until under the new limit or until all unpinned memory is freed. This will
37     *  never free pinned memory, so the cache can potentially remain over the limit. The limit is
38     *  enforced each time memory is allocated or released.
39     *  0 is a special flag for an infinite budget.
40     *  @return size_t The previous limit.
41     */
42    size_t setImageCacheLimit(size_t newLimit);
43
44    /**
45     *  Return the number of bytes of memory currently in use by the cache. Can include memory that
46     *  is no longer pinned, but has not been freed.
47     */
48    size_t getImageCacheUsed() const { return fRamUsed; }
49
50    virtual void* allocAndPinCache(size_t bytes, ID*) SK_OVERRIDE;
51    virtual void* pinCache(ID, SkImageCache::DataStatus*) SK_OVERRIDE;
52    virtual void releaseCache(ID) SK_OVERRIDE;
53    virtual void throwAwayCache(ID) SK_OVERRIDE;
54
55private:
56    // Linked list of recently used. Head is the most recently used, and tail is the least.
57    SkTInternalLList<CachedPixels> fLRU;
58    typedef SkTInternalLList<CachedPixels>::Iter Iter;
59
60#ifdef SK_DEBUG
61    // fMutex is mutable so that getMemoryStatus can be const
62    mutable
63#endif
64    SkMutex fMutex;
65    size_t  fRamBudget;
66    size_t  fRamUsed;
67
68    /**
69     *  Find the CachedPixels represented by ID, or NULL if not in the cache. Mutex must be locked
70     *  before calling.
71     */
72    CachedPixels* findByID(ID) const;
73
74    /**
75     *  If over budget, throw away pixels which are not currently in use until below budget or there
76     *  are no more pixels eligible to be thrown away. Mutex must be locked before calling.
77     */
78    void purgeIfNeeded();
79
80    /**
81     *  Purge until below limit. Mutex must be locked before calling.
82     */
83    void purgeTilAtOrBelow(size_t limit);
84
85    /**
86     *  Remove a set of CachedPixels. Mutex must be locked before calling.
87     */
88    void removePixels(CachedPixels*);
89};
90
91#endif // SkLruImageCache_DEFINED
92