Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(618)

Unified Diff: base/memory/discardable_memory_manager.cc

Issue 204733003: base: Refactor DiscardableMemoryManager for use with different type of allocations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add missing unlock call and remove unnecessary unlock call Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/memory/discardable_memory_manager.cc
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc
index fc263521015340b4687cfddc12e040f1746faf7f..ea5e45f56a55b543c71521fe305cdfd9948c2350 100644
--- a/base/memory/discardable_memory_manager.cc
+++ b/base/memory/discardable_memory_manager.cc
@@ -4,114 +4,89 @@
#include "base/memory/discardable_memory_manager.h"
-#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "base/containers/mru_cache.h"
#include "base/debug/trace_event.h"
#include "base/synchronization/lock.h"
-#include "base/sys_info.h"
namespace base {
namespace internal {
-namespace {
+DiscardableMemoryManager::AllocationInfo::AllocationInfo(size_t bytes)
+ : bytes(bytes), locked(false) {}
-// This is admittedly pretty magical. It's approximately enough memory for four
-// 2560x1600 images.
-static const size_t kDefaultDiscardableMemoryLimit = 64 * 1024 * 1024;
-static const size_t kDefaultBytesToKeepUnderModeratePressure =
- kDefaultDiscardableMemoryLimit / 4;
+DiscardableMemoryManager::AllocationInfo::~AllocationInfo() {}
-} // namespace
-
-DiscardableMemoryManager::DiscardableMemoryManager()
- : allocations_(AllocationMap::NO_AUTO_EVICT),
+DiscardableMemoryManager::DiscardableMemoryManager(
+ DiscardableMemoryAllocation::Factory* allocation_factory,
+ size_t discardable_memory_limit)
+ : allocation_factory_(allocation_factory),
+ next_allocation_id_(0),
+ allocations_(AllocationMap::NO_AUTO_EVICT),
bytes_allocated_(0),
- discardable_memory_limit_(kDefaultDiscardableMemoryLimit),
- bytes_to_keep_under_moderate_pressure_(
- kDefaultBytesToKeepUnderModeratePressure) {
-}
+ discardable_memory_limit_(discardable_memory_limit) {}
DiscardableMemoryManager::~DiscardableMemoryManager() {
DCHECK(allocations_.empty());
DCHECK_EQ(0u, bytes_allocated_);
}
-void DiscardableMemoryManager::RegisterMemoryPressureListener() {
- AutoLock lock(lock_);
- DCHECK(base::MessageLoop::current());
- DCHECK(!memory_pressure_listener_);
- memory_pressure_listener_.reset(
- new MemoryPressureListener(
- base::Bind(&DiscardableMemoryManager::OnMemoryPressure,
- Unretained(this))));
-}
-
-void DiscardableMemoryManager::UnregisterMemoryPressureListener() {
- AutoLock lock(lock_);
- DCHECK(memory_pressure_listener_);
- memory_pressure_listener_.reset();
-}
-
void DiscardableMemoryManager::SetDiscardableMemoryLimit(size_t bytes) {
AutoLock lock(lock_);
discardable_memory_limit_ = bytes;
EnforcePolicyWithLockAcquired();
}
-void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure(
+DiscardableMemoryManager::AllocationId DiscardableMemoryManager::Register(
size_t bytes) {
AutoLock lock(lock_);
- bytes_to_keep_under_moderate_pressure_ = bytes;
-}
-
-void DiscardableMemoryManager::Register(
- const DiscardableMemory* discardable, size_t bytes) {
- AutoLock lock(lock_);
+ AllocationId allocation_id = next_allocation_id_++;
+ if (next_allocation_id_ == INT_MAX)
+ next_allocation_id_ = 1;
// A registered memory listener is currently required. This DCHECK can be
// moved or removed if we decide that it's useful to relax this condition.
// TODO(reveman): Enable this DCHECK when skia and blink are able to
// register memory pressure listeners. crbug.com/333907
// DCHECK(memory_pressure_listener_);
- DCHECK(allocations_.Peek(discardable) == allocations_.end());
- allocations_.Put(discardable, Allocation(bytes));
+ DCHECK(allocations_.Peek(allocation_id) == allocations_.end());
+ allocations_.Put(allocation_id, AllocationInfo(bytes));
+ return allocation_id;
}
-void DiscardableMemoryManager::Unregister(
- const DiscardableMemory* discardable) {
+void DiscardableMemoryManager::Unregister(AllocationId allocation_id) {
AutoLock lock(lock_);
- AllocationMap::iterator it = allocations_.Peek(discardable);
+ AllocationMap::iterator it = allocations_.Peek(allocation_id);
if (it == allocations_.end())
return;
- if (it->second.memory) {
+ if (it->second.allocation.get()) {
size_t bytes = it->second.bytes;
DCHECK_LE(bytes, bytes_allocated_);
bytes_allocated_ -= bytes;
- free(it->second.memory);
+ it->second.allocation.reset();
}
allocations_.Erase(it);
}
-scoped_ptr<uint8, FreeDeleter> DiscardableMemoryManager::Acquire(
- const DiscardableMemory* discardable,
- bool* purged) {
+void* DiscardableMemoryManager::Lock(AllocationId allocation_id, bool* purged) {
AutoLock lock(lock_);
// NB: |allocations_| is an MRU cache, and use of |Get| here updates that
// cache.
- AllocationMap::iterator it = allocations_.Get(discardable);
+ AllocationMap::iterator it = allocations_.Get(allocation_id);
CHECK(it != allocations_.end());
- if (it->second.memory) {
- scoped_ptr<uint8, FreeDeleter> memory(it->second.memory);
- it->second.memory = NULL;
- *purged = false;
- return memory.Pass();
+ if (it->second.allocation.get()) {
+ DiscardableMemoryAllocation* allocation = it->second.allocation.get();
+
+ DCHECK(!it->second.locked);
+ it->second.locked = true;
+ *purged = !allocation->Lock();
+ return allocation->Memory();
}
size_t bytes = it->second.bytes;
if (!bytes)
- return scoped_ptr<uint8, FreeDeleter>();
+ return NULL;
if (discardable_memory_limit_) {
size_t limit = 0;
@@ -123,49 +98,51 @@ scoped_ptr<uint8, FreeDeleter> DiscardableMemoryManager::Acquire(
// Check for overflow.
if (std::numeric_limits<size_t>::max() - bytes < bytes_allocated_)
- return scoped_ptr<uint8, FreeDeleter>();
+ return NULL;
- scoped_ptr<uint8, FreeDeleter> memory(static_cast<uint8*>(malloc(bytes)));
- if (!memory)
- return scoped_ptr<uint8, FreeDeleter>();
+ linked_ptr<DiscardableMemoryAllocation> allocation(
+ allocation_factory_->CreateLockedAllocation(bytes).release());
+ if (!allocation.get())
+ return NULL;
+ it->second.allocation = allocation;
+ it->second.locked = true;
bytes_allocated_ += bytes;
*purged = true;
- return memory.Pass();
+ return allocation->Memory();
}
-void DiscardableMemoryManager::Release(
- const DiscardableMemory* discardable,
- scoped_ptr<uint8, FreeDeleter> memory) {
+void DiscardableMemoryManager::Unlock(AllocationId allocation_id) {
AutoLock lock(lock_);
// NB: |allocations_| is an MRU cache, and use of |Get| here updates that
// cache.
- AllocationMap::iterator it = allocations_.Get(discardable);
+ AllocationMap::iterator it = allocations_.Get(allocation_id);
CHECK(it != allocations_.end());
- DCHECK(!it->second.memory);
- it->second.memory = memory.release();
-
+ DCHECK(it->second.allocation.get());
+ DCHECK(it->second.locked);
+ it->second.locked = false;
+ it->second.allocation->Unlock();
EnforcePolicyWithLockAcquired();
}
-void DiscardableMemoryManager::PurgeAll() {
+void DiscardableMemoryManager::PurgeUntilUsageIsWithin(size_t limit) {
AutoLock lock(lock_);
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(0);
+ PurgeLRUWithLockAcquiredUntilUsageIsWithin(limit);
}
bool DiscardableMemoryManager::IsRegisteredForTest(
- const DiscardableMemory* discardable) const {
+ AllocationId allocation_id) const {
AutoLock lock(lock_);
- AllocationMap::const_iterator it = allocations_.Peek(discardable);
+ AllocationMap::const_iterator it = allocations_.Peek(allocation_id);
return it != allocations_.end();
}
bool DiscardableMemoryManager::CanBePurgedForTest(
- const DiscardableMemory* discardable) const {
+ AllocationId allocation_id) const {
AutoLock lock(lock_);
- AllocationMap::const_iterator it = allocations_.Peek(discardable);
- return it != allocations_.end() && it->second.memory;
+ AllocationMap::const_iterator it = allocations_.Peek(allocation_id);
+ return it != allocations_.end() && !it->second.locked;
}
size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
@@ -173,27 +150,6 @@ size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
return bytes_allocated_;
}
-void DiscardableMemoryManager::OnMemoryPressure(
- MemoryPressureListener::MemoryPressureLevel pressure_level) {
- switch (pressure_level) {
- case MemoryPressureListener::MEMORY_PRESSURE_MODERATE:
- Purge();
- return;
- case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL:
- PurgeAll();
- return;
- }
-
- NOTREACHED();
-}
-
-void DiscardableMemoryManager::Purge() {
- AutoLock lock(lock_);
-
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(
- bytes_to_keep_under_moderate_pressure_);
-}
-
void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
size_t limit) {
TRACE_EVENT1(
@@ -208,14 +164,15 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
++it) {
if (bytes_allocated_ <= limit)
break;
- if (!it->second.memory)
+ if (!it->second.allocation.get())
+ continue;
+ if (it->second.locked)
continue;
size_t bytes = it->second.bytes;
DCHECK_LE(bytes, bytes_allocated_);
bytes_allocated_ -= bytes;
- free(it->second.memory);
- it->second.memory = NULL;
+ it->second.allocation.reset();
}
}

Powered by Google App Engine
This is Rietveld 408576698