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 3 // found in the LICENSE file. 4 5 #include "base/memory/discardable_memory_emulated.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/memory/discardable_memory_manager.h" 9 10 namespace base { 11 namespace { 12 13 // This is admittedly pretty magical. 14 const size_t kEmulatedMemoryLimit = 512 * 1024 * 1024; 15 const size_t kEmulatedSoftMemoryLimit = 32 * 1024 * 1024; 16 const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000; 17 18 struct SharedState { SharedStatebase::__anon86984cde0111::SharedState19 SharedState() 20 : manager(kEmulatedMemoryLimit, 21 kEmulatedSoftMemoryLimit, 22 TimeDelta::FromMilliseconds( 23 kEmulatedHardMemoryLimitExpirationTimeMs)) {} 24 25 internal::DiscardableMemoryManager manager; 26 }; 27 LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; 28 29 } // namespace 30 31 namespace internal { 32 DiscardableMemoryEmulated(size_t bytes)33DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes) 34 : bytes_(bytes), 35 is_locked_(false) { 36 g_shared_state.Pointer()->manager.Register(this, bytes); 37 } 38 ~DiscardableMemoryEmulated()39DiscardableMemoryEmulated::~DiscardableMemoryEmulated() { 40 if (is_locked_) 41 Unlock(); 42 g_shared_state.Pointer()->manager.Unregister(this); 43 } 44 45 // static ReduceMemoryUsage()46bool DiscardableMemoryEmulated::ReduceMemoryUsage() { 47 return g_shared_state.Pointer()->manager.ReduceMemoryUsage(); 48 } 49 50 // static ReduceMemoryUsageUntilWithinLimit(size_t bytes)51void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit( 52 size_t bytes) { 53 g_shared_state.Pointer()->manager.ReduceMemoryUsageUntilWithinLimit(bytes); 54 } 55 56 // static PurgeForTesting()57void DiscardableMemoryEmulated::PurgeForTesting() { 58 g_shared_state.Pointer()->manager.PurgeAll(); 59 } 60 Initialize()61bool DiscardableMemoryEmulated::Initialize() { 62 return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 63 } 64 Lock()65DiscardableMemoryLockStatus DiscardableMemoryEmulated::Lock() { 66 DCHECK(!is_locked_); 67 68 bool purged = false; 69 if (!g_shared_state.Pointer()->manager.AcquireLock(this, &purged)) 70 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 71 72 is_locked_ = true; 73 return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED 74 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; 75 } 76 Unlock()77void DiscardableMemoryEmulated::Unlock() { 78 DCHECK(is_locked_); 79 g_shared_state.Pointer()->manager.ReleaseLock(this); 80 is_locked_ = false; 81 } 82 Memory() const83void* DiscardableMemoryEmulated::Memory() const { 84 DCHECK(is_locked_); 85 DCHECK(memory_); 86 return memory_.get(); 87 } 88 AllocateAndAcquireLock()89bool DiscardableMemoryEmulated::AllocateAndAcquireLock() { 90 if (memory_) 91 return true; 92 93 memory_.reset(new uint8[bytes_]); 94 return false; 95 } 96 Purge()97void DiscardableMemoryEmulated::Purge() { 98 memory_.reset(); 99 } 100 101 } // namespace internal 102 } // namespace base 103