Index: components/html_viewer/discardable_memory_allocator.cc |
diff --git a/components/html_viewer/discardable_memory_allocator.cc b/components/html_viewer/discardable_memory_allocator.cc |
index 7f362239b2d5f0c4bebd6be4c01913b4f0ee06a4..f76deeecc1148d448c4e1566c196471ab869b4d6 100644 |
--- a/components/html_viewer/discardable_memory_allocator.cc |
+++ b/components/html_viewer/discardable_memory_allocator.cc |
@@ -5,59 +5,45 @@ |
#include "components/html_viewer/discardable_memory_allocator.h" |
#include "base/memory/discardable_memory.h" |
+#include "base/memory/weak_ptr.h" |
#include "base/stl_util.h" |
namespace html_viewer { |
-// Interface to the rest of the program. These objects are owned outside of the |
-// allocator. |
-class DiscardableMemoryAllocator::DiscardableMemoryChunkImpl |
- : public base::DiscardableMemory { |
+// Represents an actual memory chunk. This is an object owned by |
+// DiscardableMemoryAllocator. DiscardableMemoryChunkImpl are passed to the |
+// rest of the program, and access this memory through a weak ptr. |
+class DiscardableMemoryAllocator::OwnedMemoryChunk { |
public: |
- DiscardableMemoryChunkImpl(size_t size, DiscardableMemoryAllocator* allocator) |
+ OwnedMemoryChunk(size_t size, DiscardableMemoryAllocator* allocator) |
: is_locked_(true), |
size_(size), |
data_(new uint8_t[size]), |
- allocator_(allocator) {} |
+ allocator_(allocator), |
+ weak_factory_(this) {} |
+ ~OwnedMemoryChunk() {} |
- ~DiscardableMemoryChunkImpl() override { |
- // Either the memory is discarded or the memory chunk is unlocked. |
- DCHECK(data_ || !is_locked_); |
- if (!is_locked_ && data_) |
- allocator_->NotifyDestructed(unlocked_position_); |
+ void Lock() { |
+ DCHECK(!is_locked_); |
+ is_locked_ = true; |
+ allocator_->NotifyLocked(unlocked_position_); |
} |
- // Overridden from DiscardableMemoryChunk: |
- bool Lock() override { |
- DCHECK(!is_locked_); |
- if (!data_) |
- return false; |
- |
- is_locked_ = true; |
- allocator_->NotifyLocked(unlocked_position_); |
- return true; |
- } |
- |
- void Unlock() override { |
+ void Unlock() { |
DCHECK(is_locked_); |
- DCHECK(data_); |
is_locked_ = false; |
unlocked_position_ = allocator_->NotifyUnlocked(this); |
} |
- void* data() const override { |
- if (data_) { |
- DCHECK(is_locked_); |
- return data_.get(); |
- } |
- return nullptr; |
+ bool is_locked() const { return is_locked_; } |
+ size_t size() const { return size_; } |
+ void* data() const { |
+ DCHECK(is_locked_); |
+ return data_.get(); |
} |
- size_t size() const { return size_; } |
- |
- void Discard() { |
- DCHECK(!is_locked_); |
- data_.reset(); |
+ base::WeakPtr<OwnedMemoryChunk> GetWeakPtr() { |
+ return weak_factory_.GetWeakPtr(); |
} |
private: |
@@ -66,10 +52,56 @@ |
scoped_ptr<uint8_t[]> data_; |
DiscardableMemoryAllocator* allocator_; |
- std::list<DiscardableMemoryChunkImpl*>::iterator unlocked_position_; |
+ std::list<OwnedMemoryChunk*>::iterator unlocked_position_; |
+ |
+ base::WeakPtrFactory<OwnedMemoryChunk> weak_factory_; |
+ |
+ DISALLOW_IMPLICIT_CONSTRUCTORS(OwnedMemoryChunk); |
+}; |
+ |
+namespace { |
+ |
+// Interface to the rest of the program. These objects are owned outside of the |
+// allocator and wrap a weak ptr. |
+class DiscardableMemoryChunkImpl : public base::DiscardableMemory { |
+ public: |
+ explicit DiscardableMemoryChunkImpl( |
+ base::WeakPtr<DiscardableMemoryAllocator::OwnedMemoryChunk> chunk) |
+ : memory_chunk_(chunk) {} |
+ ~DiscardableMemoryChunkImpl() override { |
+ // Either the memory chunk is invalid (because the backing has gone away), |
+ // or the memory chunk is unlocked (because leaving the chunk locked once |
+ // we deallocate means the chunk will never get cleaned up). |
+ DCHECK(!memory_chunk_ || !memory_chunk_->is_locked()); |
+ } |
+ |
+ // Overridden from DiscardableMemoryChunk: |
+ bool Lock() override { |
+ if (!memory_chunk_) |
+ return false; |
+ |
+ memory_chunk_->Lock(); |
+ return true; |
+ } |
+ |
+ void Unlock() override { |
+ DCHECK(memory_chunk_); |
+ memory_chunk_->Unlock(); |
+ } |
+ |
+ void* data() const override { |
+ if (memory_chunk_) |
+ return memory_chunk_->data(); |
+ return nullptr; |
+ } |
+ |
+ private: |
+ base::WeakPtr<DiscardableMemoryAllocator::OwnedMemoryChunk> memory_chunk_; |
DISALLOW_IMPLICIT_CONSTRUCTORS(DiscardableMemoryChunkImpl); |
}; |
+ |
+} // namespace |
DiscardableMemoryAllocator::DiscardableMemoryAllocator( |
size_t desired_max_memory) |
@@ -85,9 +117,7 @@ |
scoped_ptr<base::DiscardableMemory> |
DiscardableMemoryAllocator::AllocateLockedDiscardableMemory(size_t size) { |
- base::AutoLock lock(lock_); |
- scoped_ptr<DiscardableMemoryChunkImpl> chunk( |
- new DiscardableMemoryChunkImpl(size, this)); |
+ OwnedMemoryChunk* chunk = new OwnedMemoryChunk(size, this); |
total_live_memory_ += size; |
locked_chunks_++; |
@@ -98,31 +128,24 @@ |
while (total_live_memory_ > desired_max_memory_ && |
it != live_unlocked_chunks_.end()) { |
total_live_memory_ -= (*it)->size(); |
- (*it)->Discard(); |
+ delete *it; |
it = live_unlocked_chunks_.erase(it); |
} |
- return chunk.Pass(); |
+ return make_scoped_ptr(new DiscardableMemoryChunkImpl(chunk->GetWeakPtr())); |
} |
-std::list<DiscardableMemoryAllocator::DiscardableMemoryChunkImpl*>::iterator |
-DiscardableMemoryAllocator::NotifyUnlocked(DiscardableMemoryChunkImpl* chunk) { |
- base::AutoLock lock(lock_); |
+std::list<DiscardableMemoryAllocator::OwnedMemoryChunk*>::iterator |
+DiscardableMemoryAllocator::NotifyUnlocked( |
+ DiscardableMemoryAllocator::OwnedMemoryChunk* chunk) { |
locked_chunks_--; |
return live_unlocked_chunks_.insert(live_unlocked_chunks_.end(), chunk); |
} |
void DiscardableMemoryAllocator::NotifyLocked( |
- std::list<DiscardableMemoryChunkImpl*>::iterator it) { |
- base::AutoLock lock(lock_); |
+ std::list<OwnedMemoryChunk*>::iterator it) { |
locked_chunks_++; |
live_unlocked_chunks_.erase(it); |
} |
-void DiscardableMemoryAllocator::NotifyDestructed( |
- std::list<DiscardableMemoryChunkImpl*>::iterator it) { |
- base::AutoLock lock(lock_); |
- live_unlocked_chunks_.erase(it); |
-} |
- |
} // namespace html_viewer |