// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_ #define BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_ #include "base/base_export.h" #include "base/containers/hash_tables.h" #include "base/containers/mru_cache.h" #include "base/memory/memory_pressure_listener.h" #include "base/synchronization/lock.h" namespace base { class DiscardableMemory; } // namespace base #if defined(COMPILER_GCC) namespace BASE_HASH_NAMESPACE { template <> struct hash { size_t operator()(const base::DiscardableMemory* ptr) const { return hash()(reinterpret_cast(ptr)); } }; } // namespace BASE_HASH_NAMESPACE #endif // COMPILER namespace base { namespace internal { // The DiscardableMemoryProvider manages a collection of emulated // DiscardableMemory instances. It is used on platforms that do not support // discardable memory natively. It keeps track of all DiscardableMemory // instances (in case they need to be purged), and the total amount of // allocated memory (in case this forces a purge). // // When notified of memory pressure, the provider either purges the LRU // memory -- if the pressure is moderate -- or all discardable memory // if the pressure is critical. // // NB - this class is an implementation detail. It has been exposed for testing // purposes. You should not need to use this class directly. class BASE_EXPORT_PRIVATE DiscardableMemoryProvider { public: DiscardableMemoryProvider(); ~DiscardableMemoryProvider(); // The maximum number of bytes of discardable memory that may be allocated // before we force a purge. If this amount is zero, it is interpreted as // having no limit at all. void SetDiscardableMemoryLimit(size_t bytes); // Sets the amount of memory to reclaim when we're under moderate pressure. void SetBytesToReclaimUnderModeratePressure(size_t bytes); // Adds the given discardable memory to the provider's collection. void Register(const DiscardableMemory* discardable, size_t bytes); // Removes the given discardable memory from the provider's collection. void Unregister(const DiscardableMemory* discardable); // Returns NULL if an error occurred. Otherwise, returns the backing buffer // and sets |purged| to indicate whether or not the backing buffer has been // purged since last use. scoped_ptr Acquire( const DiscardableMemory* discardable, bool* purged); // Release a previously acquired backing buffer. This gives the buffer back // to the provider where it can be purged if necessary. void Release(const DiscardableMemory* discardable, scoped_ptr memory); // Purges all discardable memory. void PurgeAll(); // Returns true if discardable memory has been added to the provider's // collection. This should only be used by tests. bool IsRegisteredForTest(const DiscardableMemory* discardable) const; // Returns true if discardable memory can be purged. This should only // be used by tests. bool CanBePurgedForTest(const DiscardableMemory* discardable) const; // Returns total amount of allocated discardable memory. This should only // be used by tests. size_t GetBytesAllocatedForTest() const; private: struct Allocation { explicit Allocation(size_t bytes) : bytes(bytes), memory(NULL) { } size_t bytes; uint8* memory; }; typedef HashingMRUCache AllocationMap; // This can be called as a hint that the system is under memory pressure. void NotifyMemoryPressure( MemoryPressureListener::MemoryPressureLevel pressure_level); // Purges |bytes_to_reclaim_under_moderate_pressure_| bytes of // discardable memory. void Purge(); // Purges least recently used memory until usage is less or equal to |limit|. // Caller must acquire |lock_| prior to calling this function. void PurgeLRUWithLockAcquiredUntilUsageIsWithin(size_t limit); // Ensures that we don't allocate beyond our memory limit. // Caller must acquire |lock_| prior to calling this function. void EnforcePolicyWithLockAcquired(); // Needs to be held when accessing members. mutable Lock lock_; // A MRU cache of all allocated bits of discardable memory. Used for purging. AllocationMap allocations_; // The total amount of allocated discardable memory. size_t bytes_allocated_; // The maximum number of bytes of discardable memory that may be allocated // before we assume moderate memory pressure. size_t discardable_memory_limit_; // Under moderate memory pressure, we will purge this amount of memory. size_t bytes_to_reclaim_under_moderate_pressure_; // Allows us to be respond when the system reports that it is under memory // pressure. MemoryPressureListener memory_pressure_listener_; DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryProvider); }; } // namespace internal } // namespace base #endif // BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_