SkDiscardableMemoryPool: modernize

* Use unique_ptr, sk_sp, SkAutoFree, using.
  * Rely on thread-safe static global initializion.

Change-Id: I7c14e0e57622163b1b81b97a218b816fe6d02926
Reviewed-on: https://skia-review.googlesource.com/13818
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
Hal Canary 2017-04-19 13:17:59 -04:00 committed by Skia Commit-Bot
parent 600effbdc7
commit a294be2404
7 changed files with 36 additions and 47 deletions

View File

@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
#include "SkDiscardableMemory.h"
#include "SkDiscardableMemoryPool.h"
#include "SkImageGenerator.h"
#include "SkDiscardableMemory.h"
#include "SkMakeUnique.h"
#include "SkMalloc.h"
#include "SkMutex.h"
#include "SkOnce.h"
#include "SkTInternalLList.h"
#include "SkTemplates.h"
// Note:
// A PoolDiscardableMemory is memory that is counted in a pool.
@ -33,7 +33,10 @@ public:
DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = nullptr);
~DiscardableMemoryPool() override;
SkDiscardableMemory* create(size_t bytes) override;
std::unique_ptr<SkDiscardableMemory> make(size_t bytes);
SkDiscardableMemory* create(size_t bytes) override {
return this->make(bytes).release(); // TODO: change API
}
size_t getRAMUsed() override;
void setRAMBudget(size_t budget) override;
@ -61,7 +64,7 @@ private:
/** Function called to free memory if needed */
void dumpDownTo(size_t budget);
/** called by DiscardableMemoryPool upon destruction */
void free(PoolDiscardableMemory* dm);
void removeFromPool(PoolDiscardableMemory* dm);
/** called by DiscardableMemoryPool::lock() */
bool lock(PoolDiscardableMemory* dm);
/** called by DiscardableMemoryPool::unlock() */
@ -78,8 +81,7 @@ private:
*/
class PoolDiscardableMemory : public SkDiscardableMemory {
public:
PoolDiscardableMemory(DiscardableMemoryPool* pool,
void* pointer, size_t bytes);
PoolDiscardableMemory(sk_sp<DiscardableMemoryPool> pool, SkAutoFree pointer, size_t bytes);
~PoolDiscardableMemory() override;
bool lock() override;
void* data() override;
@ -87,29 +89,24 @@ public:
friend class DiscardableMemoryPool;
private:
SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
DiscardableMemoryPool* const fPool;
sk_sp<DiscardableMemoryPool> fPool;
bool fLocked;
void* fPointer;
SkAutoFree fPointer;
const size_t fBytes;
};
PoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
void* pointer,
PoolDiscardableMemory::PoolDiscardableMemory(sk_sp<DiscardableMemoryPool> pool,
SkAutoFree pointer,
size_t bytes)
: fPool(pool)
, fLocked(true)
, fPointer(pointer)
, fBytes(bytes) {
: fPool(std::move(pool)), fLocked(true), fPointer(std::move(pointer)), fBytes(bytes) {
SkASSERT(fPool != nullptr);
SkASSERT(fPointer != nullptr);
SkASSERT(fBytes > 0);
fPool->ref();
}
PoolDiscardableMemory::~PoolDiscardableMemory() {
SkASSERT(!fLocked); // contract for SkDiscardableMemory
fPool->free(this);
fPool->unref();
fPool->removeFromPool(this);
}
bool PoolDiscardableMemory::lock() {
@ -119,7 +116,7 @@ bool PoolDiscardableMemory::lock() {
void* PoolDiscardableMemory::data() {
SkASSERT(fLocked); // contract for SkDiscardableMemory
return fPointer;
return fPointer.get();
}
void PoolDiscardableMemory::unlock() {
@ -153,14 +150,13 @@ void DiscardableMemoryPool::dumpDownTo(size_t budget) {
if (fUsed <= budget) {
return;
}
typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
using Iter = SkTInternalLList<PoolDiscardableMemory>::Iter;
Iter iter;
PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
while ((fUsed > budget) && (cur)) {
if (!cur->fLocked) {
PoolDiscardableMemory* dm = cur;
SkASSERT(dm->fPointer != nullptr);
sk_free(dm->fPointer);
dm->fPointer = nullptr;
SkASSERT(fUsed >= dm->fBytes);
fUsed -= dm->fBytes;
@ -174,25 +170,23 @@ void DiscardableMemoryPool::dumpDownTo(size_t budget) {
}
}
SkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
void* addr = sk_malloc_flags(bytes, 0);
std::unique_ptr<SkDiscardableMemory> DiscardableMemoryPool::make(size_t bytes) {
SkAutoFree addr(sk_malloc_flags(bytes, 0));
if (nullptr == addr) {
return nullptr;
}
PoolDiscardableMemory* dm = new PoolDiscardableMemory(this, addr, bytes);
auto dm = skstd::make_unique<PoolDiscardableMemory>(sk_ref_sp(this), std::move(addr), bytes);
SkAutoMutexAcquire autoMutexAcquire(fMutex);
fList.addToHead(dm);
fList.addToHead(dm.get());
fUsed += bytes;
this->dumpDownTo(fBudget);
return dm;
return std::move(dm);
}
void DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
void DiscardableMemoryPool::removeFromPool(PoolDiscardableMemory* dm) {
SkAutoMutexAcquire autoMutexAcquire(fMutex);
// This is called by dm's destructor.
if (dm->fPointer != nullptr) {
sk_free(dm->fPointer);
dm->fPointer = nullptr;
SkASSERT(fUsed >= dm->fBytes);
fUsed -= dm->fBytes;
fList.remove(dm);
@ -242,18 +236,14 @@ void DiscardableMemoryPool::dumpPool() {
} // namespace
SkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(size_t size, SkBaseMutex* mutex) {
return new DiscardableMemoryPool(size, mutex);
sk_sp<SkDiscardableMemoryPool> SkDiscardableMemoryPool::Make(size_t size, SkBaseMutex* mutex) {
return sk_make_sp<DiscardableMemoryPool>(size, mutex);
}
SK_DECLARE_STATIC_MUTEX(gMutex);
SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
static SkOnce once;
static SkDiscardableMemoryPool* global;
once([]{
global = SkDiscardableMemoryPool::Create(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
&gMutex);
});
static SkBaseMutex gMutex;
// Intentionally leak this global pool.
static SkDiscardableMemoryPool* global =
new DiscardableMemoryPool(SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE, &gMutex);
return global;
}

View File

@ -52,8 +52,7 @@ public:
* the pool works.
* Without mutex, will be not be thread safe.
*/
static SkDiscardableMemoryPool* Create(
size_t size, SkBaseMutex* mutex = nullptr);
static sk_sp<SkDiscardableMemoryPool> Make(size_t size, SkBaseMutex* mutex = nullptr);
};
/**

View File

@ -72,7 +72,7 @@ static SkCachedData* test_locking(skiatest::Reporter* reporter,
* and when the cache is.
*/
DEF_TEST(CachedData, reporter) {
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(1000));
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(1000));
for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) {
const size_t size = 100;

View File

@ -10,7 +10,7 @@
DEF_TEST(DiscardableMemoryPool, reporter) {
sk_sp<SkDiscardableMemoryPool> pool(
SkDiscardableMemoryPool::Create(1, nullptr));
SkDiscardableMemoryPool::Make(1, nullptr));
pool->setRAMBudget(3);
REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());

View File

@ -52,8 +52,8 @@ DEF_TEST(DiscardableMemory_global, reporter) {
}
DEF_TEST(DiscardableMemory_nonglobal, reporter) {
std::unique_ptr<SkDiscardableMemoryPool> pool(
SkDiscardableMemoryPool::Create(1024, /* mutex = */ nullptr));
sk_sp<SkDiscardableMemoryPool> pool(
SkDiscardableMemoryPool::Make(1024, /* mutex = */ nullptr));
std::unique_ptr<SkDiscardableMemory> dm(pool->create(kTestStringLength));
test_dm(reporter, dm.get(), true);
}

View File

@ -121,7 +121,7 @@ DEF_TEST(ImageCache, reporter) {
test_cache(reporter, cache, true);
}
{
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(defLimit, nullptr));
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(defLimit, nullptr));
gPool = pool.get();
SkResourceCache cache(pool_factory);
test_cache(reporter, cache, true);

View File

@ -127,7 +127,7 @@ DEF_TEST(BitmapCache_discarded_bitmap, reporter) {
testBitmapCache_discarded_bitmap(reporter, &cache, nullptr);
}
{
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(byteLimit, nullptr));
sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(byteLimit, nullptr));
gPool = pool.get();
SkResourceCache::DiscardableFactory factory = pool_factory;
SkResourceCache cache(factory);