| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/discardable_memory_provider.h" | 5 #include "base/memory/discardable_memory_provider.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/containers/hash_tables.h" | 8 #include "base/containers/hash_tables.h" |
| 9 #include "base/containers/mru_cache.h" | 9 #include "base/containers/mru_cache.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/lazy_instance.h" | |
| 12 #include "base/memory/discardable_memory.h" | |
| 13 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
| 14 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
| 15 | 13 |
| 16 namespace base { | 14 namespace base { |
| 17 namespace internal { | 15 namespace internal { |
| 18 | 16 |
| 19 namespace { | 17 namespace { |
| 20 | 18 |
| 21 static base::LazyInstance<DiscardableMemoryProvider>::Leaky g_provider = | |
| 22 LAZY_INSTANCE_INITIALIZER; | |
| 23 | |
| 24 // If this is given a valid value via SetInstanceForTest, this pointer will be | |
| 25 // returned by GetInstance rather than |g_provider|. | |
| 26 static DiscardableMemoryProvider* g_provider_for_test = NULL; | |
| 27 | |
| 28 // This is admittedly pretty magical. It's approximately enough memory for two | 19 // This is admittedly pretty magical. It's approximately enough memory for two |
| 29 // 2560x1600 images. | 20 // 2560x1600 images. |
| 30 static const size_t kDefaultDiscardableMemoryLimit = 32 * 1024 * 1024; | 21 static const size_t kDefaultDiscardableMemoryLimit = 32 * 1024 * 1024; |
| 31 static const size_t kDefaultBytesToReclaimUnderModeratePressure = | 22 static const size_t kDefaultBytesToReclaimUnderModeratePressure = |
| 32 kDefaultDiscardableMemoryLimit / 2; | 23 kDefaultDiscardableMemoryLimit / 2; |
| 33 | 24 |
| 34 } // namespace | 25 } // namespace |
| 35 | 26 |
| 36 DiscardableMemoryProvider::DiscardableMemoryProvider() | 27 DiscardableMemoryProvider::DiscardableMemoryProvider() |
| 37 : allocations_(AllocationMap::NO_AUTO_EVICT), | 28 : allocations_(AllocationMap::NO_AUTO_EVICT), |
| 38 bytes_allocated_(0), | 29 bytes_allocated_(0), |
| 39 discardable_memory_limit_(kDefaultDiscardableMemoryLimit), | 30 discardable_memory_limit_(kDefaultDiscardableMemoryLimit), |
| 40 bytes_to_reclaim_under_moderate_pressure_( | 31 bytes_to_reclaim_under_moderate_pressure_( |
| 41 kDefaultBytesToReclaimUnderModeratePressure), | 32 kDefaultBytesToReclaimUnderModeratePressure), |
| 42 memory_pressure_listener_( | 33 memory_pressure_listener_( |
| 43 base::Bind(&DiscardableMemoryProvider::NotifyMemoryPressure)) { | 34 base::Bind(&DiscardableMemoryProvider::NotifyMemoryPressure, |
| 35 Unretained(this))) { |
| 44 } | 36 } |
| 45 | 37 |
| 46 DiscardableMemoryProvider::~DiscardableMemoryProvider() { | 38 DiscardableMemoryProvider::~DiscardableMemoryProvider() { |
| 47 DCHECK(allocations_.empty()); | 39 DCHECK(allocations_.empty()); |
| 48 DCHECK_EQ(0u, bytes_allocated_); | 40 DCHECK_EQ(0u, bytes_allocated_); |
| 49 } | 41 } |
| 50 | 42 |
| 51 // static | |
| 52 DiscardableMemoryProvider* DiscardableMemoryProvider::GetInstance() { | |
| 53 if (g_provider_for_test) | |
| 54 return g_provider_for_test; | |
| 55 return g_provider.Pointer(); | |
| 56 } | |
| 57 | |
| 58 // static | |
| 59 void DiscardableMemoryProvider::SetInstanceForTest( | |
| 60 DiscardableMemoryProvider* provider) { | |
| 61 g_provider_for_test = provider; | |
| 62 } | |
| 63 | |
| 64 // static | |
| 65 void DiscardableMemoryProvider::NotifyMemoryPressure( | 43 void DiscardableMemoryProvider::NotifyMemoryPressure( |
| 66 MemoryPressureListener::MemoryPressureLevel pressure_level) { | 44 MemoryPressureListener::MemoryPressureLevel pressure_level) { |
| 67 switch (pressure_level) { | 45 switch (pressure_level) { |
| 68 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: | 46 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: |
| 69 DiscardableMemoryProvider::GetInstance()->Purge(); | 47 Purge(); |
| 70 return; | 48 return; |
| 71 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: | 49 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: |
| 72 DiscardableMemoryProvider::GetInstance()->PurgeAll(); | 50 PurgeAll(); |
| 73 return; | 51 return; |
| 74 } | 52 } |
| 75 | 53 |
| 76 NOTREACHED(); | 54 NOTREACHED(); |
| 77 } | 55 } |
| 78 | 56 |
| 79 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { | 57 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { |
| 80 AutoLock lock(lock_); | 58 AutoLock lock(lock_); |
| 81 discardable_memory_limit_ = bytes; | 59 discardable_memory_limit_ = bytes; |
| 82 EnforcePolicyWithLockAcquired(); | 60 EnforcePolicyWithLockAcquired(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 it->second.memory = NULL; | 206 it->second.memory = NULL; |
| 229 } | 207 } |
| 230 } | 208 } |
| 231 | 209 |
| 232 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { | 210 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { |
| 233 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); | 211 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); |
| 234 } | 212 } |
| 235 | 213 |
| 236 } // namespace internal | 214 } // namespace internal |
| 237 } // namespace base | 215 } // namespace base |
| OLD | NEW |