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 |