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 kEmulatedBytesToKeepUnderModeratePressure = 4 * 1024 * 1024; 17 const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000; 18 19 struct SharedState { SharedStatebase::__anoncc3956cb0111::SharedState20 SharedState() 21 : manager(kEmulatedMemoryLimit, 22 kEmulatedSoftMemoryLimit, 23 kEmulatedBytesToKeepUnderModeratePressure, 24 TimeDelta::FromMilliseconds( 25 kEmulatedHardMemoryLimitExpirationTimeMs)) {} 26 27 internal::DiscardableMemoryManager manager; 28 }; 29 LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; 30 31 } // namespace 32 33 namespace internal { 34 DiscardableMemoryEmulated(size_t bytes)35DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes) 36 : bytes_(bytes), 37 is_locked_(false) { 38 g_shared_state.Pointer()->manager.Register(this, bytes); 39 } 40 ~DiscardableMemoryEmulated()41DiscardableMemoryEmulated::~DiscardableMemoryEmulated() { 42 if (is_locked_) 43 Unlock(); 44 g_shared_state.Pointer()->manager.Unregister(this); 45 } 46 47 // static RegisterMemoryPressureListeners()48void DiscardableMemoryEmulated::RegisterMemoryPressureListeners() { 49 g_shared_state.Pointer()->manager.RegisterMemoryPressureListener(); 50 } 51 52 // static UnregisterMemoryPressureListeners()53void DiscardableMemoryEmulated::UnregisterMemoryPressureListeners() { 54 g_shared_state.Pointer()->manager.UnregisterMemoryPressureListener(); 55 } 56 57 // static ReduceMemoryUsage()58bool DiscardableMemoryEmulated::ReduceMemoryUsage() { 59 return g_shared_state.Pointer()->manager.ReduceMemoryUsage(); 60 } 61 62 // static PurgeForTesting()63void DiscardableMemoryEmulated::PurgeForTesting() { 64 g_shared_state.Pointer()->manager.PurgeAll(); 65 } 66 Initialize()67bool DiscardableMemoryEmulated::Initialize() { 68 return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 69 } 70 Lock()71DiscardableMemoryLockStatus DiscardableMemoryEmulated::Lock() { 72 DCHECK(!is_locked_); 73 74 bool purged = false; 75 if (!g_shared_state.Pointer()->manager.AcquireLock(this, &purged)) 76 return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 77 78 is_locked_ = true; 79 return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED 80 : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; 81 } 82 Unlock()83void DiscardableMemoryEmulated::Unlock() { 84 DCHECK(is_locked_); 85 g_shared_state.Pointer()->manager.ReleaseLock(this); 86 is_locked_ = false; 87 } 88 Memory() const89void* DiscardableMemoryEmulated::Memory() const { 90 DCHECK(is_locked_); 91 DCHECK(memory_); 92 return memory_.get(); 93 } 94 AllocateAndAcquireLock()95bool DiscardableMemoryEmulated::AllocateAndAcquireLock() { 96 if (memory_) 97 return true; 98 99 memory_.reset(new uint8[bytes_]); 100 return false; 101 } 102 Purge()103void DiscardableMemoryEmulated::Purge() { 104 memory_.reset(); 105 } 106 107 } // namespace internal 108 } // namespace base 109