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"
1078358bf624c7e7c09ffccf638c50870808d884d6mtklein#include "SkLazyPtr.h"
11cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org#include "SkTInternalLList.h"
12cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org#include "SkThread.h"
132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// Note:
152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// A PoolDiscardableMemory is memory that is counted in a pool.
162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com// A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
18cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgnamespace {
19cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
20cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass PoolDiscardableMemory;
21cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com/**
23cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  This non-global pool can be used for unit tests to verify that the
24cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  pool works.
252c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com */
26cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass DiscardableMemoryPool : public SkDiscardableMemoryPool {
272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.compublic:
28cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /**
29cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org     *  Without mutex, will be not be thread safe.
30cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org     */
31cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
32cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual ~DiscardableMemoryPool();
33cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
34cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
35cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
36cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual size_t getRAMUsed() SK_OVERRIDE;
37cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void setRAMBudget(size_t budget) SK_OVERRIDE;
38cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual size_t getRAMBudget() SK_OVERRIDE { return fBudget; }
39cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
40cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** purges all unlocked DMs */
41cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void dumpPool() SK_OVERRIDE;
42cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
43cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS  // Defined in SkDiscardableMemoryPool.h
44cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual int getCacheHits() SK_OVERRIDE { return fCacheHits; }
45cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual int getCacheMisses() SK_OVERRIDE { return fCacheMisses; }
46cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual void resetCacheHitsAndMisses() SK_OVERRIDE {
47cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        fCacheHits = fCacheMisses = 0;
48cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    }
49cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    int          fCacheHits;
50cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    int          fCacheMisses;
51cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
52cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
53cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgprivate:
54cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SkBaseMutex* fMutex;
55cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    size_t       fBudget;
56cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    size_t       fUsed;
57cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SkTInternalLList<PoolDiscardableMemory> fList;
58cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
59cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** Function called to free memory if needed */
60cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void dumpDownTo(size_t budget);
61cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool upon destruction */
62cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void free(PoolDiscardableMemory* dm);
63cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool::lock() */
64cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    bool lock(PoolDiscardableMemory* dm);
65cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    /** called by DiscardableMemoryPool::unlock() */
66cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void unlock(PoolDiscardableMemory* dm);
67cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
68cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    friend class PoolDiscardableMemory;
69cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
70cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    typedef SkDiscardableMemory::Factory INHERITED;
71cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org};
72cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
73cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org/**
74cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  A PoolDiscardableMemory is a SkDiscardableMemory that relies on
75cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org *  a DiscardableMemoryPool object to manage the memory.
76cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org */
77cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgclass PoolDiscardableMemory : public SkDiscardableMemory {
78cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgpublic:
79cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory(DiscardableMemoryPool* pool,
802c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                            void* pointer, size_t bytes);
81cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    virtual ~PoolDiscardableMemory();
822c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual bool lock() SK_OVERRIDE;
832c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual void* data() SK_OVERRIDE;
842c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    virtual void unlock() SK_OVERRIDE;
85cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    friend class DiscardableMemoryPool;
862c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comprivate:
87cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
88cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    DiscardableMemoryPool* const fPool;
89cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    bool                         fLocked;
90cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    void*                        fPointer;
91cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    const size_t                 fBytes;
922c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com};
932c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
94cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgPoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
95cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             void* pointer,
96cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             size_t bytes)
972c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    : fPool(pool)
982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fLocked(true)
992c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fPointer(pointer)
1002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fBytes(bytes) {
1012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fPool != NULL);
1022c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fPointer != NULL);
1032c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fBytes > 0);
1042c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->ref();
1052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1062c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
107cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgPoolDiscardableMemory::~PoolDiscardableMemory() {
1081d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(!fLocked); // contract for SkDiscardableMemory
1092c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->free(this);
1102c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->unref();
1112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
113cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgbool PoolDiscardableMemory::lock() {
1141d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(!fLocked); // contract for SkDiscardableMemory
1152c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return fPool->lock(this);
1162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1172c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
118cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid* PoolDiscardableMemory::data() {
1191d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(fLocked); // contract for SkDiscardableMemory
1201d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    return fPointer;
1212c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
123cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid PoolDiscardableMemory::unlock() {
1241d0654f69d1d0c3bb565fba018a11c77f25bc55ereed@google.com    SkASSERT(fLocked); // contract for SkDiscardableMemory
1252c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fPool->unlock(this);
1262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
1282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
1292c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
130cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgDiscardableMemoryPool::DiscardableMemoryPool(size_t budget,
131cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org                                             SkBaseMutex* mutex)
1322c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    : fMutex(mutex)
1332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fBudget(budget)
1342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    , fUsed(0) {
135cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS
1362c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fCacheHits = 0;
1372c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fCacheMisses = 0;
138cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
1392c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
140cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgDiscardableMemoryPool::~DiscardableMemoryPool() {
141cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    // PoolDiscardableMemory objects that belong to this pool are
1422c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // always deleted before deleting this pool since each one has a
1432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // ref to the pool.
1442c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(fList.isEmpty());
1452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
147cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::dumpDownTo(size_t budget) {
1489b7906672eb6794497d560761aa8bab824a13a90halcanary    if (fMutex != NULL) {
1499b7906672eb6794497d560761aa8bab824a13a90halcanary        fMutex->assertHeld();
1509b7906672eb6794497d560761aa8bab824a13a90halcanary    }
1512c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (fUsed <= budget) {
1522c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return;
1532c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
154cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
1552c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    Iter iter;
156cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
1572c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    while ((fUsed > budget) && (NULL != cur)) {
1582c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        if (!cur->fLocked) {
159cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org            PoolDiscardableMemory* dm = cur;
1602c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            SkASSERT(dm->fPointer != NULL);
1612c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            sk_free(dm->fPointer);
1622c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            dm->fPointer = NULL;
1632c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            SkASSERT(fUsed >= dm->fBytes);
1642c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            fUsed -= dm->fBytes;
1652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            cur = iter.prev();
1662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            // Purged DMs are taken out of the list.  This saves times
1672c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            // looking them up.  Purged DMs are NOT deleted.
1682c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            fList.remove(dm);
1692c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        } else {
1702c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com            cur = iter.prev();
1712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        }
1722c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
1732c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1742c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
175cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgSkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
1762c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    void* addr = sk_malloc_flags(bytes, 0);
1772c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == addr) {
1782c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return NULL;
1792c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
180cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    PoolDiscardableMemory* dm = SkNEW_ARGS(PoolDiscardableMemory,
1812c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com                                             (this, addr, bytes));
1822c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
1832c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.addToHead(dm);
1842c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fUsed += bytes;
1852c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
1862c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return dm;
1872c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
1882c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
189cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
1902c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    // This is called by dm's destructor.
1912c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (dm->fPointer != NULL) {
1922c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoMutexAcquire autoMutexAcquire(fMutex);
1932c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        sk_free(dm->fPointer);
1942c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        dm->fPointer = NULL;
1952c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT(fUsed >= dm->fBytes);
1962c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        fUsed -= dm->fBytes;
1972c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        fList.remove(dm);
1982c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    } else {
1992c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkASSERT(!fList.isInList(dm));
2002c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2012c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2022c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
203cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgbool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
2042c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(dm != NULL);
2052c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == dm->fPointer) {
206cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #if SK_LAZY_CACHE_STATS
2072c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        SkAutoMutexAcquire autoMutexAcquire(fMutex);
2082c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        ++fCacheMisses;
209cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #endif  // SK_LAZY_CACHE_STATS
2102c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return false;
2112c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2122c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2132c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    if (NULL == dm->fPointer) {
2142c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        // May have been purged while waiting for lock.
215cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #if SK_LAZY_CACHE_STATS
2162c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        ++fCacheMisses;
217cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org        #endif  // SK_LAZY_CACHE_STATS
2182c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com        return false;
2192c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    }
2202c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    dm->fLocked = true;
2212c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.remove(dm);
2222c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fList.addToHead(dm);
223cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #if SK_LAZY_CACHE_STATS
2242c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    ++fCacheHits;
225cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    #endif  // SK_LAZY_CACHE_STATS
2262c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return true;
2272c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2282c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
229cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
2302c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkASSERT(dm != NULL);
2312c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2322c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    dm->fLocked = false;
2332c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
2342c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2352c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
236cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgsize_t DiscardableMemoryPool::getRAMUsed() {
2372c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    return fUsed;
2382c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
239cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::setRAMBudget(size_t budget) {
2402c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2412c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    fBudget = budget;
2422c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(fBudget);
2432c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
244cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.orgvoid DiscardableMemoryPool::dumpPool() {
2452c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    SkAutoMutexAcquire autoMutexAcquire(fMutex);
2462c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com    this->dumpDownTo(0);
2472c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2482c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2492c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
2502c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comSK_DECLARE_STATIC_MUTEX(gMutex);
25178358bf624c7e7c09ffccf638c50870808d884d6mtkleinSkDiscardableMemoryPool* create_global_pool() {
25278358bf624c7e7c09ffccf638c50870808d884d6mtklein    return SkDiscardableMemoryPool::Create(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
25378358bf624c7e7c09ffccf638c50870808d884d6mtklein                                           &gMutex);
2542c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
25578358bf624c7e7c09ffccf638c50870808d884d6mtklein
256cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org}  // namespace
257cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
25878358bf624c7e7c09ffccf638c50870808d884d6mtkleinSkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(size_t size, SkBaseMutex* mutex) {
259cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org    return SkNEW_ARGS(DiscardableMemoryPool, (size, mutex));
260cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org}
261cf2f00872c559c892bb4b466bf678c7667490ccecommit-bot@chromium.org
2622c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.comSkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
26378358bf624c7e7c09ffccf638c50870808d884d6mtklein    SK_DECLARE_STATIC_LAZY_PTR(SkDiscardableMemoryPool, global, create_global_pool);
26478358bf624c7e7c09ffccf638c50870808d884d6mtklein    return global.get();
2652c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com}
2662c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com
2677e2b0f3b06351cf5bd9f6130f6bfb950cfc2cb75commit-bot@chromium.org// defined in SkImageGenerator.h
2687e2b0f3b06351cf5bd9f6130f6bfb950cfc2cb75commit-bot@chromium.orgvoid SkPurgeGlobalDiscardableMemoryPool() {
2697e2b0f3b06351cf5bd9f6130f6bfb950cfc2cb75commit-bot@chromium.org    SkGetGlobalDiscardableMemoryPool()->dumpPool();
2707e2b0f3b06351cf5bd9f6130f6bfb950cfc2cb75commit-bot@chromium.org}
2712c7c7ee47d75e7815ea8db05e924ab55958cb402halcanary@google.com////////////////////////////////////////////////////////////////////////////////
272