Home | History | Annotate | Download | only in memory
      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 {
     19   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 
     33 DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes)
     34     : bytes_(bytes),
     35       is_locked_(false) {
     36   g_shared_state.Pointer()->manager.Register(this, bytes);
     37 }
     38 
     39 DiscardableMemoryEmulated::~DiscardableMemoryEmulated() {
     40   if (is_locked_)
     41     Unlock();
     42   g_shared_state.Pointer()->manager.Unregister(this);
     43 }
     44 
     45 // static
     46 bool DiscardableMemoryEmulated::ReduceMemoryUsage() {
     47   return g_shared_state.Pointer()->manager.ReduceMemoryUsage();
     48 }
     49 
     50 // static
     51 void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit(
     52     size_t bytes) {
     53   g_shared_state.Pointer()->manager.ReduceMemoryUsageUntilWithinLimit(bytes);
     54 }
     55 
     56 // static
     57 void DiscardableMemoryEmulated::PurgeForTesting() {
     58   g_shared_state.Pointer()->manager.PurgeAll();
     59 }
     60 
     61 bool DiscardableMemoryEmulated::Initialize() {
     62   return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
     63 }
     64 
     65 DiscardableMemoryLockStatus 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 
     77 void DiscardableMemoryEmulated::Unlock() {
     78   DCHECK(is_locked_);
     79   g_shared_state.Pointer()->manager.ReleaseLock(this);
     80   is_locked_ = false;
     81 }
     82 
     83 void* DiscardableMemoryEmulated::Memory() const {
     84   DCHECK(is_locked_);
     85   DCHECK(memory_);
     86   return memory_.get();
     87 }
     88 
     89 bool DiscardableMemoryEmulated::AllocateAndAcquireLock() {
     90   if (memory_)
     91     return true;
     92 
     93   memory_.reset(new uint8[bytes_]);
     94   return false;
     95 }
     96 
     97 void DiscardableMemoryEmulated::Purge() {
     98   memory_.reset();
     99 }
    100 
    101 }  // namespace internal
    102 }  // namespace base
    103