Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #ifndef mozalloc_VolatileBuffer_h
6 : #define mozalloc_VolatileBuffer_h
7 :
8 : #include "mozilla/mozalloc.h"
9 : #include "mozilla/Mutex.h"
10 : #include "mozilla/RefPtr.h"
11 : #include "mozilla/MemoryReporting.h"
12 : #include "mozilla/RefCounted.h"
13 :
14 : /* VolatileBuffer
15 : *
16 : * This class represents a piece of memory that can potentially be reclaimed
17 : * by the OS when not in use. As long as there are one or more
18 : * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain
19 : * available. However, when there are no VolatileBufferPtrs holding a
20 : * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make
21 : * better decisions about what pages to purge than we can.
22 : *
23 : * VolatileBuffers may not always be volatile - if the allocation is too small,
24 : * or if the OS doesn't support the feature, or if the OS doesn't want to,
25 : * the buffer will be allocated on heap.
26 : *
27 : * VolatileBuffer allocations are fallible. They are intended for uses where
28 : * one may allocate large buffers for caching data. Init() must be called
29 : * exactly once.
30 : *
31 : * After getting a reference to VolatileBuffer using VolatileBufferPtr,
32 : * WasPurged() can be used to check if the OS purged any pages in the buffer.
33 : * The OS cannot purge a buffer immediately after a VolatileBuffer is
34 : * initialized. At least one VolatileBufferPtr must be created before the
35 : * buffer can be purged, so the first use of VolatileBufferPtr does not need
36 : * to check WasPurged().
37 : *
38 : * When a buffer is purged, some or all of the buffer is zeroed out. This
39 : * API cannot tell which parts of the buffer were lost.
40 : *
41 : * VolatileBuffer and VolatileBufferPtr are threadsafe.
42 : */
43 :
44 : namespace mozilla {
45 :
46 : class VolatileBuffer
47 : {
48 : friend class VolatileBufferPtr_base;
49 : public:
50 : MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer)
51 100 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VolatileBuffer)
52 :
53 : VolatileBuffer();
54 :
55 : /* aAlignment must be a multiple of the pointer size */
56 : bool Init(size_t aSize, size_t aAlignment = sizeof(void*));
57 :
58 : size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
59 : size_t NonHeapSizeOfExcludingThis() const;
60 : bool OnHeap() const;
61 :
62 : protected:
63 : bool Lock(void** aBuf);
64 : void Unlock();
65 :
66 : private:
67 : ~VolatileBuffer();
68 :
69 : /**
70 : * Protects mLockCount, mFirstLock, and changes to the volatility of our
71 : * buffer. Other member variables are read-only except in Init() and the
72 : * destructor.
73 : */
74 : Mutex mMutex;
75 :
76 : void* mBuf;
77 : size_t mSize;
78 : int mLockCount;
79 : #if defined(ANDROID)
80 : int mFd;
81 : #elif defined(XP_DARWIN)
82 : bool mHeap;
83 : #elif defined(XP_WIN)
84 : bool mHeap;
85 : bool mFirstLock;
86 : #endif
87 : };
88 :
89 : class VolatileBufferPtr_base {
90 : public:
91 50 : explicit VolatileBufferPtr_base(VolatileBuffer* vbuf)
92 50 : : mVBuf(vbuf)
93 : , mMapping(nullptr)
94 50 : , mPurged(false)
95 : {
96 50 : Lock();
97 50 : }
98 :
99 0 : ~VolatileBufferPtr_base() {
100 0 : Unlock();
101 0 : }
102 :
103 285 : bool WasBufferPurged() const {
104 285 : return mPurged;
105 : }
106 :
107 : protected:
108 : RefPtr<VolatileBuffer> mVBuf;
109 : void* mMapping;
110 :
111 50 : void Set(VolatileBuffer* vbuf) {
112 50 : Unlock();
113 50 : mVBuf = vbuf;
114 50 : Lock();
115 50 : }
116 :
117 : private:
118 : bool mPurged;
119 :
120 100 : void Lock() {
121 100 : if (mVBuf) {
122 50 : mPurged = !mVBuf->Lock(&mMapping);
123 : } else {
124 50 : mMapping = nullptr;
125 50 : mPurged = false;
126 : }
127 100 : }
128 :
129 50 : void Unlock() {
130 50 : if (mVBuf) {
131 0 : mVBuf->Unlock();
132 : }
133 50 : }
134 : };
135 :
136 : template <class T>
137 0 : class VolatileBufferPtr : public VolatileBufferPtr_base
138 : {
139 : public:
140 : explicit VolatileBufferPtr(VolatileBuffer* vbuf) : VolatileBufferPtr_base(vbuf) {}
141 50 : VolatileBufferPtr() : VolatileBufferPtr_base(nullptr) {}
142 :
143 : VolatileBufferPtr(VolatileBufferPtr&& aOther)
144 : : VolatileBufferPtr_base(aOther.mVBuf)
145 : {
146 : aOther.Set(nullptr);
147 : }
148 :
149 335 : operator T*() const {
150 335 : return (T*) mMapping;
151 : }
152 :
153 50 : VolatileBufferPtr& operator=(VolatileBuffer* aVBuf)
154 : {
155 50 : Set(aVBuf);
156 50 : return *this;
157 : }
158 :
159 : VolatileBufferPtr& operator=(VolatileBufferPtr&& aOther)
160 : {
161 : MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
162 : Set(aOther.mVBuf);
163 : aOther.Set(nullptr);
164 : return *this;
165 : }
166 :
167 : private:
168 : VolatileBufferPtr(VolatileBufferPtr const& vbufptr) = delete;
169 : };
170 :
171 : } // namespace mozilla
172 :
173 : #endif /* mozalloc_VolatileBuffer_h */
|