michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozalloc_VolatileBuffer_h michael@0: #define mozalloc_VolatileBuffer_h michael@0: michael@0: #include "mozilla/mozalloc.h" michael@0: #include "mozilla/RefPtr.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "mozilla/NullPtr.h" michael@0: michael@0: /* VolatileBuffer michael@0: * michael@0: * This class represents a piece of memory that can potentially be reclaimed michael@0: * by the OS when not in use. As long as there are one or more michael@0: * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain michael@0: * available. However, when there are no VolatileBufferPtrs holding a michael@0: * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make michael@0: * better decisions about what pages to purge than we can. michael@0: * michael@0: * VolatileBuffers may not always be volatile - if the allocation is too small, michael@0: * or if the OS doesn't support the feature, or if the OS doesn't want to, michael@0: * the buffer will be allocated on heap. michael@0: * michael@0: * VolatileBuffer allocations are fallible. They are intended for uses where michael@0: * one may allocate large buffers for caching data. Init() must be called michael@0: * exactly once. michael@0: * michael@0: * After getting a reference to VolatileBuffer using VolatileBufferPtr, michael@0: * WasPurged() can be used to check if the OS purged any pages in the buffer. michael@0: * The OS cannot purge a buffer immediately after a VolatileBuffer is michael@0: * initialized. At least one VolatileBufferPtr must be created before the michael@0: * buffer can be purged, so the first use of VolatileBufferPtr does not need michael@0: * to check WasPurged(). michael@0: * michael@0: * When a buffer is purged, some or all of the buffer is zeroed out. This michael@0: * API cannot tell which parts of the buffer were lost. michael@0: * michael@0: * VolatileBuffer is not thread safe. Do not use VolatileBufferPtrs on michael@0: * different threads. michael@0: */ michael@0: michael@0: namespace mozilla { michael@0: michael@0: class MOZALLOC_EXPORT VolatileBuffer : public RefCounted michael@0: { michael@0: friend class VolatileBufferPtr_base; michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer) michael@0: VolatileBuffer(); michael@0: ~VolatileBuffer(); michael@0: michael@0: /* aAlignment must be a multiple of the pointer size */ michael@0: bool Init(size_t aSize, size_t aAlignment = sizeof(void*)); michael@0: michael@0: size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; michael@0: size_t NonHeapSizeOfExcludingThis() const; michael@0: bool OnHeap() const; michael@0: michael@0: protected: michael@0: bool Lock(void** aBuf); michael@0: void Unlock(); michael@0: michael@0: private: michael@0: void* mBuf; michael@0: size_t mSize; michael@0: int mLockCount; michael@0: #if defined(ANDROID) michael@0: int mFd; michael@0: #elif defined(XP_DARWIN) michael@0: bool mHeap; michael@0: #elif defined(XP_WIN) michael@0: bool mHeap; michael@0: bool mFirstLock; michael@0: #endif michael@0: }; michael@0: michael@0: class VolatileBufferPtr_base { michael@0: public: michael@0: VolatileBufferPtr_base(VolatileBuffer* vbuf) : mVBuf(vbuf) { michael@0: if (vbuf) { michael@0: mPurged = !vbuf->Lock(&mMapping); michael@0: } else { michael@0: mMapping = nullptr; michael@0: mPurged = false; michael@0: } michael@0: } michael@0: michael@0: ~VolatileBufferPtr_base() { michael@0: if (mVBuf) { michael@0: mVBuf->Unlock(); michael@0: } michael@0: } michael@0: michael@0: bool WasBufferPurged() const { michael@0: return mPurged; michael@0: } michael@0: michael@0: protected: michael@0: void* mMapping; michael@0: michael@0: private: michael@0: RefPtr mVBuf; michael@0: bool mPurged; michael@0: }; michael@0: michael@0: template michael@0: class VolatileBufferPtr : public VolatileBufferPtr_base michael@0: { michael@0: public: michael@0: VolatileBufferPtr(VolatileBuffer* vbuf) : VolatileBufferPtr_base(vbuf) {} michael@0: michael@0: operator T*() const { michael@0: return (T*) mMapping; michael@0: } michael@0: }; michael@0: michael@0: }; /* namespace mozilla */ michael@0: michael@0: #endif /* mozalloc_VolatileBuffer_h */