1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/html_viewer/discardable_memory_allocator.h"
7 #include "base/memory/discardable_memory.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/stl_util.h"
11 namespace html_viewer
{
13 // Represents an actual memory chunk. This is an object owned by
14 // DiscardableMemoryAllocator. DiscardableMemoryChunkImpl are passed to the
15 // rest of the program, and access this memory through a weak ptr.
16 class DiscardableMemoryAllocator::OwnedMemoryChunk
{
18 OwnedMemoryChunk(size_t size
, DiscardableMemoryAllocator
* allocator
)
21 data_(new uint8_t[size
]),
22 allocator_(allocator
),
23 weak_factory_(this) {}
24 ~OwnedMemoryChunk() {}
29 allocator_
->NotifyLocked(unlocked_position_
);
35 unlocked_position_
= allocator_
->NotifyUnlocked(this);
38 bool is_locked() const { return is_locked_
; }
39 size_t size() const { return size_
; }
45 base::WeakPtr
<OwnedMemoryChunk
> GetWeakPtr() {
46 return weak_factory_
.GetWeakPtr();
52 scoped_ptr
<uint8_t[]> data_
;
53 DiscardableMemoryAllocator
* allocator_
;
55 std::list
<OwnedMemoryChunk
*>::iterator unlocked_position_
;
57 base::WeakPtrFactory
<OwnedMemoryChunk
> weak_factory_
;
59 DISALLOW_IMPLICIT_CONSTRUCTORS(OwnedMemoryChunk
);
64 // Interface to the rest of the program. These objects are owned outside of the
65 // allocator and wrap a weak ptr.
66 class DiscardableMemoryChunkImpl
: public base::DiscardableMemory
{
68 explicit DiscardableMemoryChunkImpl(
69 base::WeakPtr
<DiscardableMemoryAllocator::OwnedMemoryChunk
> chunk
)
70 : memory_chunk_(chunk
) {}
71 ~DiscardableMemoryChunkImpl() override
{
72 // Either the memory chunk is invalid (because the backing has gone away),
73 // or the memory chunk is unlocked (because leaving the chunk locked once
74 // we deallocate means the chunk will never get cleaned up).
75 DCHECK(!memory_chunk_
|| !memory_chunk_
->is_locked());
78 // Overridden from DiscardableMemoryChunk:
79 bool Lock() override
{
83 memory_chunk_
->Lock();
87 void Unlock() override
{
88 DCHECK(memory_chunk_
);
89 memory_chunk_
->Unlock();
92 void* data() const override
{
94 return memory_chunk_
->data();
99 base::WeakPtr
<DiscardableMemoryAllocator::OwnedMemoryChunk
> memory_chunk_
;
101 DISALLOW_IMPLICIT_CONSTRUCTORS(DiscardableMemoryChunkImpl
);
106 DiscardableMemoryAllocator::DiscardableMemoryAllocator(
107 size_t desired_max_memory
)
108 : desired_max_memory_(desired_max_memory
),
109 total_live_memory_(0u),
113 DiscardableMemoryAllocator::~DiscardableMemoryAllocator() {
114 DCHECK_EQ(0, locked_chunks_
);
115 STLDeleteElements(&live_unlocked_chunks_
);
118 scoped_ptr
<base::DiscardableMemory
>
119 DiscardableMemoryAllocator::AllocateLockedDiscardableMemory(size_t size
) {
120 OwnedMemoryChunk
* chunk
= new OwnedMemoryChunk(size
, this);
121 total_live_memory_
+= size
;
124 // Go through the list of unlocked live chunks starting from the least
125 // recently used, freeing as many as we can until we get our size under the
127 auto it
= live_unlocked_chunks_
.begin();
128 while (total_live_memory_
> desired_max_memory_
&&
129 it
!= live_unlocked_chunks_
.end()) {
130 total_live_memory_
-= (*it
)->size();
132 it
= live_unlocked_chunks_
.erase(it
);
135 return make_scoped_ptr(new DiscardableMemoryChunkImpl(chunk
->GetWeakPtr()));
138 std::list
<DiscardableMemoryAllocator::OwnedMemoryChunk
*>::iterator
139 DiscardableMemoryAllocator::NotifyUnlocked(
140 DiscardableMemoryAllocator::OwnedMemoryChunk
* chunk
) {
142 return live_unlocked_chunks_
.insert(live_unlocked_chunks_
.end(), chunk
);
145 void DiscardableMemoryAllocator::NotifyLocked(
146 std::list
<OwnedMemoryChunk
*>::iterator it
) {
148 live_unlocked_chunks_
.erase(it
);
151 } // namespace html_viewer