• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)35 DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes)
36     : bytes_(bytes),
37       is_locked_(false) {
38   g_shared_state.Pointer()->manager.Register(this, bytes);
39 }
40 
~DiscardableMemoryEmulated()41 DiscardableMemoryEmulated::~DiscardableMemoryEmulated() {
42   if (is_locked_)
43     Unlock();
44   g_shared_state.Pointer()->manager.Unregister(this);
45 }
46 
47 // static
RegisterMemoryPressureListeners()48 void DiscardableMemoryEmulated::RegisterMemoryPressureListeners() {
49   g_shared_state.Pointer()->manager.RegisterMemoryPressureListener();
50 }
51 
52 // static
UnregisterMemoryPressureListeners()53 void DiscardableMemoryEmulated::UnregisterMemoryPressureListeners() {
54   g_shared_state.Pointer()->manager.UnregisterMemoryPressureListener();
55 }
56 
57 // static
ReduceMemoryUsage()58 bool DiscardableMemoryEmulated::ReduceMemoryUsage() {
59   return g_shared_state.Pointer()->manager.ReduceMemoryUsage();
60 }
61 
62 // static
PurgeForTesting()63 void DiscardableMemoryEmulated::PurgeForTesting() {
64   g_shared_state.Pointer()->manager.PurgeAll();
65 }
66 
Initialize()67 bool DiscardableMemoryEmulated::Initialize() {
68   return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
69 }
70 
Lock()71 DiscardableMemoryLockStatus 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()83 void DiscardableMemoryEmulated::Unlock() {
84   DCHECK(is_locked_);
85   g_shared_state.Pointer()->manager.ReleaseLock(this);
86   is_locked_ = false;
87 }
88 
Memory() const89 void* DiscardableMemoryEmulated::Memory() const {
90   DCHECK(is_locked_);
91   DCHECK(memory_);
92   return memory_.get();
93 }
94 
AllocateAndAcquireLock()95 bool DiscardableMemoryEmulated::AllocateAndAcquireLock() {
96   if (memory_)
97     return true;
98 
99   memory_.reset(new uint8[bytes_]);
100   return false;
101 }
102 
Purge()103 void DiscardableMemoryEmulated::Purge() {
104   memory_.reset();
105 }
106 
107 }  // namespace internal
108 }  // namespace base
109