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 10namespace base { 11namespace { 12 13// This is admittedly pretty magical. 14const size_t kEmulatedMemoryLimit = 512 * 1024 * 1024; 15const size_t kEmulatedSoftMemoryLimit = 32 * 1024 * 1024; 16const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000; 17 18struct SharedState { 19 SharedState() 20 : manager(kEmulatedMemoryLimit, 21 kEmulatedSoftMemoryLimit, 22 TimeDelta::FromMilliseconds( 23 kEmulatedHardMemoryLimitExpirationTimeMs)) {} 24 25 internal::DiscardableMemoryManager manager; 26}; 27LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; 28 29} // namespace 30 31namespace internal { 32 33DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes) 34 : bytes_(bytes), 35 is_locked_(false) { 36 g_shared_state.Pointer()->manager.Register(this, bytes); 37} 38 39DiscardableMemoryEmulated::~DiscardableMemoryEmulated() { 40 if (is_locked_) 41 Unlock(); 42 g_shared_state.Pointer()->manager.Unregister(this); 43} 44 45// static 46bool DiscardableMemoryEmulated::ReduceMemoryUsage() { 47 return g_shared_state.Pointer()->manager.ReduceMemoryUsage(); 48} 49 50// static 51void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit( 52 size_t bytes) { 53 g_shared_state.Pointer()->manager.ReduceMemoryUsageUntilWithinLimit(bytes); 54} 55 56// static 57void DiscardableMemoryEmulated::PurgeForTesting() { 58 g_shared_state.Pointer()->manager.PurgeAll(); 59} 60 61bool DiscardableMemoryEmulated::Initialize() { 62 return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; 63} 64 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 77void DiscardableMemoryEmulated::Unlock() { 78 DCHECK(is_locked_); 79 g_shared_state.Pointer()->manager.ReleaseLock(this); 80 is_locked_ = false; 81} 82 83void* DiscardableMemoryEmulated::Memory() const { 84 DCHECK(is_locked_); 85 DCHECK(memory_); 86 return memory_.get(); 87} 88 89bool DiscardableMemoryEmulated::AllocateAndAcquireLock() { 90 if (memory_) 91 return true; 92 93 memory_.reset(new uint8[bytes_]); 94 return false; 95} 96 97void DiscardableMemoryEmulated::Purge() { 98 memory_.reset(); 99} 100 101} // namespace internal 102} // namespace base 103