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, this)) { |
44 } | 35 } |
45 | 36 |
46 DiscardableMemoryProvider::~DiscardableMemoryProvider() { | 37 DiscardableMemoryProvider::~DiscardableMemoryProvider() { |
47 DCHECK(allocations_.empty()); | 38 DCHECK(allocations_.empty()); |
48 DCHECK_EQ(0u, bytes_allocated_); | 39 DCHECK_EQ(0u, bytes_allocated_); |
49 } | 40 } |
50 | 41 |
51 // static | 42 // 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( |
| 44 DiscardableMemoryProvider* provider, |
66 MemoryPressureListener::MemoryPressureLevel pressure_level) { | 45 MemoryPressureListener::MemoryPressureLevel pressure_level) { |
67 switch (pressure_level) { | 46 switch (pressure_level) { |
68 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: | 47 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: |
69 DiscardableMemoryProvider::GetInstance()->Purge(); | 48 provider->Purge(); |
70 return; | 49 return; |
71 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: | 50 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: |
72 DiscardableMemoryProvider::GetInstance()->PurgeAll(); | 51 provider->PurgeAll(); |
73 return; | 52 return; |
74 } | 53 } |
75 | 54 |
76 NOTREACHED(); | 55 NOTREACHED(); |
77 } | 56 } |
78 | 57 |
79 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { | 58 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { |
80 AutoLock lock(lock_); | 59 AutoLock lock(lock_); |
81 discardable_memory_limit_ = bytes; | 60 discardable_memory_limit_ = bytes; |
82 EnforcePolicyWithLockAcquired(); | 61 EnforcePolicyWithLockAcquired(); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 it->second.memory = NULL; | 207 it->second.memory = NULL; |
229 } | 208 } |
230 } | 209 } |
231 | 210 |
232 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { | 211 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { |
233 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); | 212 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); |
234 } | 213 } |
235 | 214 |
236 } // namespace internal | 215 } // namespace internal |
237 } // namespace base | 216 } // namespace base |
OLD | NEW |