Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / html_viewer / discardable_memory_allocator.cc
blob79bc9e5eb95d653bd8f2d582cf0ccfd95dc603fb
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"
9 #include "base/trace_event/memory_allocator_dump.h"
10 #include "base/trace_event/memory_dump_manager.h"
11 #include "base/trace_event/process_memory_dump.h"
13 namespace html_viewer {
15 // Interface to the rest of the program. These objects are owned outside of the
16 // allocator.
17 class DiscardableMemoryAllocator::DiscardableMemoryChunkImpl
18 : public base::DiscardableMemory {
19 public:
20 DiscardableMemoryChunkImpl(size_t size, DiscardableMemoryAllocator* allocator)
21 : is_locked_(true),
22 size_(size),
23 data_(new uint8_t[size]),
24 allocator_(allocator) {}
26 ~DiscardableMemoryChunkImpl() override {
27 base::AutoLock lock(allocator_->lock_);
28 // Either the memory is discarded or the memory chunk is unlocked.
29 DCHECK(data_ || !is_locked_);
30 if (!is_locked_ && data_)
31 allocator_->NotifyDestructed(unlocked_position_);
34 // Overridden from DiscardableMemoryChunk:
35 bool Lock() override {
36 base::AutoLock lock(allocator_->lock_);
37 DCHECK(!is_locked_);
38 if (!data_)
39 return false;
41 is_locked_ = true;
42 allocator_->NotifyLocked(unlocked_position_);
43 return true;
46 void Unlock() override {
47 base::AutoLock lock(allocator_->lock_);
48 DCHECK(is_locked_);
49 DCHECK(data_);
50 is_locked_ = false;
51 unlocked_position_ = allocator_->NotifyUnlocked(this);
54 void* data() const override {
55 if (data_) {
56 DCHECK(is_locked_);
57 return data_.get();
59 return nullptr;
62 base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
63 const char* name,
64 base::trace_event::ProcessMemoryDump* pmd) const override {
65 base::trace_event::MemoryAllocatorDump* dump =
66 pmd->CreateAllocatorDump(name);
67 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
68 base::trace_event::MemoryAllocatorDump::kUnitsBytes, size_);
70 // Memory is allocated from system allocator (malloc).
71 pmd->AddSuballocation(dump->guid(),
72 base::trace_event::MemoryDumpManager::GetInstance()
73 ->system_allocator_pool_name());
74 return dump;
77 size_t size() const { return size_; }
79 void Discard() {
80 allocator_->lock_.AssertAcquired();
81 DCHECK(!is_locked_);
82 data_.reset();
85 private:
86 bool is_locked_;
87 size_t size_;
88 scoped_ptr<uint8_t[]> data_;
89 DiscardableMemoryAllocator* allocator_;
91 std::list<DiscardableMemoryChunkImpl*>::iterator unlocked_position_;
93 DISALLOW_IMPLICIT_CONSTRUCTORS(DiscardableMemoryChunkImpl);
96 DiscardableMemoryAllocator::DiscardableMemoryAllocator(
97 size_t desired_max_memory)
98 : desired_max_memory_(desired_max_memory),
99 total_live_memory_(0u),
100 locked_chunks_(0) {
103 DiscardableMemoryAllocator::~DiscardableMemoryAllocator() {
104 DCHECK_EQ(0, locked_chunks_);
105 STLDeleteElements(&live_unlocked_chunks_);
108 scoped_ptr<base::DiscardableMemory>
109 DiscardableMemoryAllocator::AllocateLockedDiscardableMemory(size_t size) {
110 base::AutoLock lock(lock_);
111 scoped_ptr<DiscardableMemoryChunkImpl> chunk(
112 new DiscardableMemoryChunkImpl(size, this));
113 total_live_memory_ += size;
114 locked_chunks_++;
116 // Go through the list of unlocked live chunks starting from the least
117 // recently used, freeing as many as we can until we get our size under the
118 // desired maximum.
119 auto it = live_unlocked_chunks_.begin();
120 while (total_live_memory_ > desired_max_memory_ &&
121 it != live_unlocked_chunks_.end()) {
122 total_live_memory_ -= (*it)->size();
123 (*it)->Discard();
124 it = live_unlocked_chunks_.erase(it);
127 return chunk.Pass();
130 std::list<DiscardableMemoryAllocator::DiscardableMemoryChunkImpl*>::iterator
131 DiscardableMemoryAllocator::NotifyUnlocked(DiscardableMemoryChunkImpl* chunk) {
132 lock_.AssertAcquired();
133 locked_chunks_--;
134 return live_unlocked_chunks_.insert(live_unlocked_chunks_.end(), chunk);
137 void DiscardableMemoryAllocator::NotifyLocked(
138 std::list<DiscardableMemoryChunkImpl*>::iterator it) {
139 lock_.AssertAcquired();
140 locked_chunks_++;
141 live_unlocked_chunks_.erase(it);
144 void DiscardableMemoryAllocator::NotifyDestructed(
145 std::list<DiscardableMemoryChunkImpl*>::iterator it) {
146 lock_.AssertAcquired();
147 live_unlocked_chunks_.erase(it);
150 } // namespace html_viewer