|
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/RefPtr.h" |
|
10 #include "mozilla/MemoryReporting.h" |
|
11 #include "mozilla/NullPtr.h" |
|
12 |
|
13 /* VolatileBuffer |
|
14 * |
|
15 * This class represents a piece of memory that can potentially be reclaimed |
|
16 * by the OS when not in use. As long as there are one or more |
|
17 * VolatileBufferPtrs holding on to a VolatileBuffer, the memory will remain |
|
18 * available. However, when there are no VolatileBufferPtrs holding a |
|
19 * VolatileBuffer, the OS can purge the pages if it wants to. The OS can make |
|
20 * better decisions about what pages to purge than we can. |
|
21 * |
|
22 * VolatileBuffers may not always be volatile - if the allocation is too small, |
|
23 * or if the OS doesn't support the feature, or if the OS doesn't want to, |
|
24 * the buffer will be allocated on heap. |
|
25 * |
|
26 * VolatileBuffer allocations are fallible. They are intended for uses where |
|
27 * one may allocate large buffers for caching data. Init() must be called |
|
28 * exactly once. |
|
29 * |
|
30 * After getting a reference to VolatileBuffer using VolatileBufferPtr, |
|
31 * WasPurged() can be used to check if the OS purged any pages in the buffer. |
|
32 * The OS cannot purge a buffer immediately after a VolatileBuffer is |
|
33 * initialized. At least one VolatileBufferPtr must be created before the |
|
34 * buffer can be purged, so the first use of VolatileBufferPtr does not need |
|
35 * to check WasPurged(). |
|
36 * |
|
37 * When a buffer is purged, some or all of the buffer is zeroed out. This |
|
38 * API cannot tell which parts of the buffer were lost. |
|
39 * |
|
40 * VolatileBuffer is not thread safe. Do not use VolatileBufferPtrs on |
|
41 * different threads. |
|
42 */ |
|
43 |
|
44 namespace mozilla { |
|
45 |
|
46 class MOZALLOC_EXPORT VolatileBuffer : public RefCounted<VolatileBuffer> |
|
47 { |
|
48 friend class VolatileBufferPtr_base; |
|
49 public: |
|
50 MOZ_DECLARE_REFCOUNTED_TYPENAME(VolatileBuffer) |
|
51 VolatileBuffer(); |
|
52 ~VolatileBuffer(); |
|
53 |
|
54 /* aAlignment must be a multiple of the pointer size */ |
|
55 bool Init(size_t aSize, size_t aAlignment = sizeof(void*)); |
|
56 |
|
57 size_t HeapSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; |
|
58 size_t NonHeapSizeOfExcludingThis() const; |
|
59 bool OnHeap() const; |
|
60 |
|
61 protected: |
|
62 bool Lock(void** aBuf); |
|
63 void Unlock(); |
|
64 |
|
65 private: |
|
66 void* mBuf; |
|
67 size_t mSize; |
|
68 int mLockCount; |
|
69 #if defined(ANDROID) |
|
70 int mFd; |
|
71 #elif defined(XP_DARWIN) |
|
72 bool mHeap; |
|
73 #elif defined(XP_WIN) |
|
74 bool mHeap; |
|
75 bool mFirstLock; |
|
76 #endif |
|
77 }; |
|
78 |
|
79 class VolatileBufferPtr_base { |
|
80 public: |
|
81 VolatileBufferPtr_base(VolatileBuffer* vbuf) : mVBuf(vbuf) { |
|
82 if (vbuf) { |
|
83 mPurged = !vbuf->Lock(&mMapping); |
|
84 } else { |
|
85 mMapping = nullptr; |
|
86 mPurged = false; |
|
87 } |
|
88 } |
|
89 |
|
90 ~VolatileBufferPtr_base() { |
|
91 if (mVBuf) { |
|
92 mVBuf->Unlock(); |
|
93 } |
|
94 } |
|
95 |
|
96 bool WasBufferPurged() const { |
|
97 return mPurged; |
|
98 } |
|
99 |
|
100 protected: |
|
101 void* mMapping; |
|
102 |
|
103 private: |
|
104 RefPtr<VolatileBuffer> mVBuf; |
|
105 bool mPurged; |
|
106 }; |
|
107 |
|
108 template <class T> |
|
109 class VolatileBufferPtr : public VolatileBufferPtr_base |
|
110 { |
|
111 public: |
|
112 VolatileBufferPtr(VolatileBuffer* vbuf) : VolatileBufferPtr_base(vbuf) {} |
|
113 |
|
114 operator T*() const { |
|
115 return (T*) mMapping; |
|
116 } |
|
117 }; |
|
118 |
|
119 }; /* namespace mozilla */ |
|
120 |
|
121 #endif /* mozalloc_VolatileBuffer_h */ |