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/stl_util.h"
10 namespace html_viewer
{
12 // Interface to the rest of the program. These objects are owned outside of the
14 class DiscardableMemoryAllocator::DiscardableMemoryChunkImpl
15 : public base::DiscardableMemory
{
17 DiscardableMemoryChunkImpl(size_t size
, DiscardableMemoryAllocator
* allocator
)
20 data_(new uint8_t[size
]),
21 allocator_(allocator
) {}
23 ~DiscardableMemoryChunkImpl() override
{
24 // Either the memory is discarded or the memory chunk is unlocked.
25 DCHECK(data_
|| !is_locked_
);
26 if (!is_locked_
&& data_
)
27 allocator_
->NotifyDestructed(unlocked_position_
);
30 // Overridden from DiscardableMemoryChunk:
31 bool Lock() override
{
37 allocator_
->NotifyLocked(unlocked_position_
);
41 void Unlock() override
{
45 unlocked_position_
= allocator_
->NotifyUnlocked(this);
48 void* data() const override
{
56 size_t size() const { return size_
; }
66 scoped_ptr
<uint8_t[]> data_
;
67 DiscardableMemoryAllocator
* allocator_
;
69 std::list
<DiscardableMemoryChunkImpl
*>::iterator unlocked_position_
;
71 DISALLOW_IMPLICIT_CONSTRUCTORS(DiscardableMemoryChunkImpl
);
74 DiscardableMemoryAllocator::DiscardableMemoryAllocator(
75 size_t desired_max_memory
)
76 : desired_max_memory_(desired_max_memory
),
77 total_live_memory_(0u),
81 DiscardableMemoryAllocator::~DiscardableMemoryAllocator() {
82 DCHECK_EQ(0, locked_chunks_
);
83 STLDeleteElements(&live_unlocked_chunks_
);
86 scoped_ptr
<base::DiscardableMemory
>
87 DiscardableMemoryAllocator::AllocateLockedDiscardableMemory(size_t size
) {
88 base::AutoLock
lock(lock_
);
89 scoped_ptr
<DiscardableMemoryChunkImpl
> chunk(
90 new DiscardableMemoryChunkImpl(size
, this));
91 total_live_memory_
+= size
;
94 // Go through the list of unlocked live chunks starting from the least
95 // recently used, freeing as many as we can until we get our size under the
97 auto it
= live_unlocked_chunks_
.begin();
98 while (total_live_memory_
> desired_max_memory_
&&
99 it
!= live_unlocked_chunks_
.end()) {
100 total_live_memory_
-= (*it
)->size();
102 it
= live_unlocked_chunks_
.erase(it
);
108 std::list
<DiscardableMemoryAllocator::DiscardableMemoryChunkImpl
*>::iterator
109 DiscardableMemoryAllocator::NotifyUnlocked(DiscardableMemoryChunkImpl
* chunk
) {
110 base::AutoLock
lock(lock_
);
112 return live_unlocked_chunks_
.insert(live_unlocked_chunks_
.end(), chunk
);
115 void DiscardableMemoryAllocator::NotifyLocked(
116 std::list
<DiscardableMemoryChunkImpl
*>::iterator it
) {
117 base::AutoLock
lock(lock_
);
119 live_unlocked_chunks_
.erase(it
);
122 void DiscardableMemoryAllocator::NotifyDestructed(
123 std::list
<DiscardableMemoryChunkImpl
*>::iterator it
) {
124 base::AutoLock
lock(lock_
);
125 live_unlocked_chunks_
.erase(it
);
128 } // namespace html_viewer