12c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com/*
22c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com * Copyright 2013 Google Inc.
32c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com *
42c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com * Use of this source code is governed by a BSD-style license that can be
52c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com * found in the LICENSE file.
62c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com */
72c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
8cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org#include "SkDiscardableMemory.h"
92c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com#include "SkDiscardableMemoryPool.h"
10fa37a21be54444189187584ce09c9a431abf1911halcanary#include "SkImageGenerator.h"
1178358bf624c7e7c09ffccf638c50870808d884d6mtklein#include "SkLazyPtr.h"
12cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org#include "SkTInternalLList.h"
13cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org#include "SkThread.h"
142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// Note:
162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// A PoolDiscardableMemory is memory that is counted in a pool.
172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
19cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgnamespace {
20cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
21cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass PoolDiscardableMemory;
22cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
232c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com/**
24cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  This non-global pool can be used for unit tests to verify that the
25cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  pool works.
262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com */
27cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass DiscardableMemoryPool : public SkDiscardableMemoryPool {
282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.compublic:
29cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /**
30cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org     *  Without mutex, will be not be thread safe.
31cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org     */
32cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
33cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual ~DiscardableMemoryPool();
34cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
35cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
36cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
37cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual size_t getRAMUsed() SK_OVERRIDE;
38cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void setRAMBudget(size_t budget) SK_OVERRIDE;
39cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual size_t getRAMBudget() SK_OVERRIDE { return fBudget; }
40cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
41cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** purges all unlocked DMs */
42cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void dumpPool() SK_OVERRIDE;
43cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
44cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS  // Defined in SkDiscardableMemoryPool.h
45cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual int getCacheHits() SK_OVERRIDE { return fCacheHits; }
46cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual int getCacheMisses() SK_OVERRIDE { return fCacheMisses; }
47cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void resetCacheHitsAndMisses() SK_OVERRIDE {
48cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        fCacheHits = fCacheMisses = 0;
49cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    }
50cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    int          fCacheHits;
51cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    int          fCacheMisses;
52cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
53cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
54cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgprivate:
55cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SkBaseMutex* fMutex;
56cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    size_t       fBudget;
57cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    size_t       fUsed;
58cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SkTInternalLList<PoolDiscardableMemory> fList;
59cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
60cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** Function called to free memory if needed */
61cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void dumpDownTo(size_t budget);
62cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool upon destruction */
63cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void free(PoolDiscardableMemory* dm);
64cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool::lock() */
65cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    bool lock(PoolDiscardableMemory* dm);
66cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool::unlock() */
67cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void unlock(PoolDiscardableMemory* dm);
68cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
69cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    friend class PoolDiscardableMemory;
70cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
71cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    typedef SkDiscardableMemory::Factory INHERITED;
72cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org};
73cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
74cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org/**
75cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  A PoolDiscardableMemory is a SkDiscardableMemory that relies on
76cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  a DiscardableMemoryPool object to manage the memory.
77cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org */
78cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass PoolDiscardableMemory : public SkDiscardableMemory {
79cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgpublic:
80cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory(DiscardableMemoryPool* pool,
812c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                            void* pointer, size_t bytes);
82cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual ~PoolDiscardableMemory();
832c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual bool lock() SK_OVERRIDE;
842c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual void* data() SK_OVERRIDE;
852c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual void unlock() SK_OVERRIDE;
86cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    friend class DiscardableMemoryPool;
872c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comprivate:
88cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
89cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    DiscardableMemoryPool* const fPool;
90cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    bool                         fLocked;
91cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void*                        fPointer;
92cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    const size_t                 fBytes;
932c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
942c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
95cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgPoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
96cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             void* pointer,
97cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             size_t bytes)
982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    : fPool(pool)
992c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fLocked(true)
1002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fPointer(pointer)
1012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fBytes(bytes) {
1022c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fPool != NULL);
1032c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fPointer != NULL);
1042c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fBytes > 0);
1052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->ref();
1062c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1072c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
108cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgPoolDiscardableMemory::~PoolDiscardableMemory() {
1091d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(!fLocked); // contract for SkDiscardableMemory
1102c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->free(this);
1112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->unref();
1122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
114cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgbool PoolDiscardableMemory::lock() {
1151d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(!fLocked); // contract for SkDiscardableMemory
1162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return fPool->lock(this);
1172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
119cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid* PoolDiscardableMemory::data() {
1201d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(fLocked); // contract for SkDiscardableMemory
1211d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    return fPointer;
1222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1232c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
124cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid PoolDiscardableMemory::unlock() {
1251d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(fLocked); // contract for SkDiscardableMemory
1262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->unlock(this);
1272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
1292c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1302c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
131cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgDiscardableMemoryPool::DiscardableMemoryPool(size_t budget,
132cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             SkBaseMutex* mutex)
1332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    : fMutex(mutex)
1342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fBudget(budget)
1352c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fUsed(0) {
136cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS
1372c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fCacheHits = 0;
1382c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fCacheMisses = 0;
139cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
1402c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
141cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgDiscardableMemoryPool::~DiscardableMemoryPool() {
142cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    // PoolDiscardableMemory objects that belong to this pool are
1432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // always deleted before deleting this pool since each one has a
1442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // ref to the pool.
1452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fList.isEmpty());
1462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
148cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::dumpDownTo(size_t budget) {
1499b7906672eb6794497d560761aa8bab824a13a90halcanary    if (fMutex != NULL) {
1509b7906672eb6794497d560761aa8bab824a13a90halcanary        fMutex->assertHeld();
1519b7906672eb6794497d560761aa8bab824a13a90halcanary    }
1522c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (fUsed <= budget) {
1532c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return;
1542c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
155cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
1562c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    Iter iter;
157cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
15849f085dddff10473b6ebf832a974288300224e60bsalomon    while ((fUsed > budget) && (cur)) {
1592c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        if (!cur->fLocked) {
160cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org            PoolDiscardableMemory* dm = cur;
1612c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            SkASSERT(dm->fPointer != NULL);
1622c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            sk_free(dm->fPointer);
1632c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            dm->fPointer = NULL;
1642c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            SkASSERT(fUsed >= dm->fBytes);
1652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            fUsed -= dm->fBytes;
1662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            cur = iter.prev();
1672c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            // Purged DMs are taken out of the list.  This saves times
1682c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            // looking them up.  Purged DMs are NOT deleted.
1692c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            fList.remove(dm);
1702c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        } else {
1712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            cur = iter.prev();
1722c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
1732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
1742c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1752c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
176cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgSkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
1772c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    void* addr = sk_malloc_flags(bytes, 0);
1782c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == addr) {
1792c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return NULL;
1802c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
181cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory* dm = SkNEW_ARGS(PoolDiscardableMemory,
1822c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                                             (this, addr, bytes));
1832c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
1842c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.addToHead(dm);
1852c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fUsed += bytes;
1862c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
1872c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return dm;
1882c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1892c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
190cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
1912c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // This is called by dm's destructor.
1922c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (dm->fPointer != NULL) {
1932c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoMutexAcquire autoMutexAcquire(fMutex);
1942c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        sk_free(dm->fPointer);
1952c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        dm->fPointer = NULL;
1962c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT(fUsed >= dm->fBytes);
1972c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        fUsed -= dm->fBytes;
1982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        fList.remove(dm);
1992c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else {
2002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT(!fList.isInList(dm));
2012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2022c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2032c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
204cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgbool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
2052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(dm != NULL);
2062c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == dm->fPointer) {
207cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #if SK_LAZY_CACHE_STATS
2082c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoMutexAcquire autoMutexAcquire(fMutex);
2092c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        ++fCacheMisses;
210cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #endif  // SK_LAZY_CACHE_STATS
2112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return false;
2122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == dm->fPointer) {
2152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        // May have been purged while waiting for lock.
216cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #if SK_LAZY_CACHE_STATS
2172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        ++fCacheMisses;
218cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #endif  // SK_LAZY_CACHE_STATS
2192c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return false;
2202c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2212c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    dm->fLocked = true;
2222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.remove(dm);
2232c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.addToHead(dm);
224cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS
2252c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    ++fCacheHits;
226cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
2272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return true;
2282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2292c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
230cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
2312c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(dm != NULL);
2322c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    dm->fLocked = false;
2342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
2352c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2362c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
237cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgsize_t DiscardableMemoryPool::getRAMUsed() {
2382c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return fUsed;
2392c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
240cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::setRAMBudget(size_t budget) {
2412c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2422c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fBudget = budget;
2432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
2442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
245cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::dumpPool() {
2462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(0);
2482c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2492c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2502c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
2512c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comSK_DECLARE_STATIC_MUTEX(gMutex);
25278358bf624c7e7c09ffccf638c50870808d884d6mtkleinSkDiscardableMemoryPool* create_global_pool() {
25378358bf624c7e7c09ffccf638c50870808d884d6mtklein    return SkDiscardableMemoryPool::Create(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
25478358bf624c7e7c09ffccf638c50870808d884d6mtklein                                           &gMutex);
2552c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
25678358bf624c7e7c09ffccf638c50870808d884d6mtklein
257cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org}  // namespace
258cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
25978358bf624c7e7c09ffccf638c50870808d884d6mtkleinSkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(size_t size, SkBaseMutex* mutex) {
260cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    return SkNEW_ARGS(DiscardableMemoryPool, (size, mutex));
261cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org}
262cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
2632c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comSkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
26478358bf624c7e7c09ffccf638c50870808d884d6mtklein    SK_DECLARE_STATIC_LAZY_PTR(SkDiscardableMemoryPool, global, create_global_pool);
26578358bf624c7e7c09ffccf638c50870808d884d6mtklein    return global.get();
2662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2672c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2682c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
269