5c862a2db5b73b2d1392afcbea904b73cdf1789c
[pdfium.git] / core / src / fxcrt / fx_basic_memmgr.cpp
1 // Copyright 2014 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/fxcrt/fx_basic.h"
8 #include "mem_int.h"
9 void FXMEM_DestroyFoxitMgr(FXMEM_FoxitMgr* pFoxitMgr)
10 {
11     if (pFoxitMgr == NULL) {
12         return;
13     }
14     CFX_MemoryMgr* p = (CFX_MemoryMgr*)pFoxitMgr;
15     if (p->m_pSystemMgr->CollectAll) {
16         p->m_pSystemMgr->CollectAll(p->m_pSystemMgr);
17     }
18     if (p->m_bReleaseMgr) {
19         p->m_pSystemMgr->Free(p->m_pSystemMgr, p, 0);
20     }
21     if (p->m_pExternalMemory) {
22         free(p->m_pExternalMemory);
23     }
24 }
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 static void* _DefAllocDebug(IFX_Allocator* pAllocator, size_t size, FX_LPCSTR filename, int line)
29 {
30     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->AllocDebug(size, 0, filename, line);
31 }
32 static void* _DefAlloc(IFX_Allocator* pAllocator, size_t size)
33 {
34     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Alloc(size, 0);
35 }
36 static void* _DefReallocDebug(IFX_Allocator* pAllocator, void* p, size_t size, FX_LPCSTR filename, int line)
37 {
38     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->ReallocDebug(p, size, 0, filename, line);
39 }
40 static void* _DefRealloc(IFX_Allocator* pAllocator, void* p, size_t size)
41 {
42     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Realloc(p, size, 0);
43 }
44 static void _DefFree(IFX_Allocator* pAllocator, void* p)
45 {
46     ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Free(p, 0);
47 }
48 #ifdef __cplusplus
49 }
50 #endif
51 void CFX_MemoryMgr::Init(FXMEM_SystemMgr* pSystemMgr)
52 {
53     m_pSystemMgr = pSystemMgr;
54     IFX_Allocator &ac = m_DefAllocator.m_Allocator;
55     ac.m_Alloc = _DefAlloc;
56     ac.m_AllocDebug = _DefAllocDebug;
57     ac.m_Realloc = _DefRealloc;
58     ac.m_ReallocDebug = _DefReallocDebug;
59     ac.m_Free = _DefFree;
60     m_DefAllocator.m_pFoxitMgr = this;
61     m_pExternalMemory = NULL;
62     m_bReleaseMgr = TRUE;
63 }
64 void CFX_MemoryMgr::PurgeMgr()
65 {
66     if (m_pSystemMgr->Purge) {
67         m_pSystemMgr->Purge(m_pSystemMgr);
68     }
69 }
70 void* CFX_MemoryMgr::Alloc(size_t size, int flags)
71 {
72     void* p = m_pSystemMgr->Alloc(m_pSystemMgr, size, flags);
73     if (p == NULL) {
74         return NULL;
75     }
76     return p;
77 }
78 void* CFX_MemoryMgr::AllocDebug(size_t size, int flags, FX_LPCSTR file, int line)
79 {
80     void* p = m_pSystemMgr->AllocDebug(m_pSystemMgr, size, flags, file, line);
81     if (p == NULL) {
82         return NULL;
83     }
84     return p;
85 }
86 void* CFX_MemoryMgr::Realloc(void* p, size_t size, int flags)
87 {
88     void* p1 = m_pSystemMgr->Realloc(m_pSystemMgr, p, size, flags);
89     if (p1 == NULL) {
90         return NULL;
91     }
92     return p1;
93 }
94 void* CFX_MemoryMgr::ReallocDebug(void* p, size_t size, int flags, FX_LPCSTR file, int line)
95 {
96     void* p1 = m_pSystemMgr->ReallocDebug(m_pSystemMgr, p, size, flags, file, line);
97     if (p1 == NULL) {
98         return NULL;
99     }
100     return p1;
101 }
102 void CFX_MemoryMgr::Free(void* p, int flags)
103 {
104     if (p == NULL) {
105         return;
106     }
107     m_pSystemMgr->Free(m_pSystemMgr, p, flags);
108 }
109 CFX_MemoryMgr* g_pDefFoxitMgr = NULL;
110 void* FXMEM_DefaultAlloc(size_t size, int flags)
111 {
112     return g_pDefFoxitMgr->Alloc(size, flags);
113 }
114 void* FXMEM_DefaultAlloc2(size_t size, size_t unit, int flags)
115 {
116     return g_pDefFoxitMgr->Alloc(size * unit, flags);
117 }
118 void* FXMEM_DefaultRealloc(void* p, size_t size, int flags)
119 {
120     if (p == NULL) {
121         return FXMEM_DefaultAlloc(size, flags);
122     }
123     return g_pDefFoxitMgr->Realloc(p, size, flags);
124 }
125 void* FXMEM_DefaultRealloc2(void* p, size_t size, size_t unit, int flags)
126 {
127     if (p == NULL) {
128         return FXMEM_DefaultAlloc2(size, unit, flags);
129     }
130     return g_pDefFoxitMgr->Realloc(p, size * unit, flags);
131 }
132 void* FXMEM_DefaultAllocDebug(size_t size, int flags, FX_LPCSTR file, int line)
133 {
134     return g_pDefFoxitMgr->AllocDebug(size, flags, file, line);
135 }
136 void* FXMEM_DefaultAllocDebug2(size_t size, size_t unit, int flags, FX_LPCSTR file, int line)
137 {
138     return g_pDefFoxitMgr->AllocDebug(size * unit, flags, file, line);
139 }
140 void* FXMEM_DefaultReallocDebug(void* p, size_t size, int flags, FX_LPCSTR file, int line)
141 {
142     if (p == NULL) {
143         return FXMEM_DefaultAllocDebug(size, flags, file, line);
144     }
145     return g_pDefFoxitMgr->ReallocDebug(p, size, flags, file, line);
146 }
147 void* FXMEM_DefaultReallocDebug2(void* p, size_t size, size_t unit, int flags, FX_LPCSTR file, int line)
148 {
149     if (p == NULL) {
150         return FXMEM_DefaultAllocDebug2(size, unit, flags, file, line);
151     }
152     return g_pDefFoxitMgr->ReallocDebug(p, size * unit, flags, file, line);
153 }
154 void FXMEM_DefaultFree(void* p, int flags)
155 {
156     g_pDefFoxitMgr->Free(p, flags);
157 }
158 IFX_Allocator* FXMEM_GetDefAllocator()
159 {
160     return &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
161 }
162 void* CFX_Object::operator new(size_t size)
163 {
164     return g_pDefFoxitMgr->Alloc(size, 0);
165 }
166 void* CFX_Object::operator new[](size_t size)
167 {
168     return g_pDefFoxitMgr->Alloc(size, 0);
169 }
170 void* CFX_Object::operator new[](size_t size, FX_LPCSTR file, int line)
171 {
172     return g_pDefFoxitMgr->AllocDebug(size, 0, file, line);
173 }
174 void* CFX_Object::operator new(size_t size, FX_LPCSTR file, int line)
175 {
176     return g_pDefFoxitMgr->AllocDebug(size, 0, file, line);
177 }
178 void CFX_Object::operator delete(void* p)
179 {
180     g_pDefFoxitMgr->Free(p, 0);
181 }
182 void CFX_Object::operator delete[](void* p)
183 {
184     g_pDefFoxitMgr->Free(p, 0);
185 }
186 void CFX_Object::operator delete(void* p, FX_LPCSTR file, int line)
187 {
188     g_pDefFoxitMgr->Free(p, 0);
189 }
190 void CFX_Object::operator delete[](void* p, FX_LPCSTR file, int line)
191 {
192     g_pDefFoxitMgr->Free(p, 0);
193 }
194 void* CFX_AllocObject::operator new(size_t size, IFX_Allocator* pAllocator, FX_LPCSTR filename, int line)
195 {
196     void* p = pAllocator ? pAllocator->m_AllocDebug(pAllocator, size, filename, line) :
197               g_pDefFoxitMgr->AllocDebug(size, 0, filename, line);
198     ((CFX_AllocObject*)p)->m_pAllocator = pAllocator;
199     return p;
200 }
201 void CFX_AllocObject::operator delete (void* p, IFX_Allocator* pAllocator, FX_LPCSTR filename, int line)
202 {
203     if (pAllocator) {
204         pAllocator->m_Free(pAllocator, p);
205     } else {
206         g_pDefFoxitMgr->Free(p, 0);
207     }
208 }
209 void* CFX_AllocObject::operator new(size_t size, IFX_Allocator* pAllocator)
210 {
211     void* p = pAllocator ? pAllocator->m_Alloc(pAllocator, size) : g_pDefFoxitMgr->Alloc(size, 0);
212     ((CFX_AllocObject*)p)->m_pAllocator = pAllocator;
213     return p;
214 }
215 void CFX_AllocObject::operator delete(void* p)
216 {
217     if (((CFX_AllocObject*)p)->m_pAllocator) {
218         (((CFX_AllocObject*)p)->m_pAllocator)->m_Free(((CFX_AllocObject*)p)->m_pAllocator, p);
219     } else {
220         g_pDefFoxitMgr->Free(p, 0);
221     }
222 }
223 void CFX_AllocObject::operator delete(void* p, IFX_Allocator* pAllocator)
224 {
225     if (pAllocator) {
226         pAllocator->m_Free(pAllocator, p);
227     } else {
228         g_pDefFoxitMgr->Free(p, 0);
229     }
230 }
231 extern "C" {
232     static void* _GOPAllocDebug(IFX_Allocator* pAllocator, size_t size, FX_LPCSTR file, int line)
233     {
234         return ((CFX_GrowOnlyPool*)pAllocator)->Alloc(size);
235     }
236     static void* _GOPAlloc(IFX_Allocator* pAllocator, size_t size)
237     {
238         return ((CFX_GrowOnlyPool*)pAllocator)->Alloc(size);
239     }
240     static void* _GOPReallocDebug(IFX_Allocator* pAllocator, void* p, size_t new_size, FX_LPCSTR file, int line)
241     {
242         return ((CFX_GrowOnlyPool*)pAllocator)->Realloc(p, new_size);
243     }
244     static void* _GOPRealloc(IFX_Allocator* pAllocator, void* p, size_t new_size)
245     {
246         return ((CFX_GrowOnlyPool*)pAllocator)->Realloc(p, new_size);
247     }
248     static void _GOPFree(IFX_Allocator* pAllocator, void* p)
249     {
250     }
251 };
252 CFX_GrowOnlyPool::CFX_GrowOnlyPool(IFX_Allocator* pAllocator, size_t trunk_size)
253 {
254     m_TrunkSize = trunk_size;
255     m_pFirstTrunk = NULL;
256     m_pAllocator = pAllocator ? pAllocator : &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
257     m_AllocDebug = _GOPAllocDebug;
258     m_Alloc = _GOPAlloc;
259     m_ReallocDebug = _GOPReallocDebug;
260     m_Realloc = _GOPRealloc;
261     m_Free = _GOPFree;
262 }
263 CFX_GrowOnlyPool::~CFX_GrowOnlyPool()
264 {
265     FreeAll();
266 }
267 void CFX_GrowOnlyPool::SetAllocator(IFX_Allocator* pAllocator)
268 {
269     ASSERT(m_pFirstTrunk == NULL);
270     m_pAllocator = pAllocator ? pAllocator : &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
271 }
272 struct _FX_GrowOnlyTrunk {
273     size_t      m_Size;
274     size_t      m_Allocated;
275     _FX_GrowOnlyTrunk*  m_pNext;
276 };
277 void CFX_GrowOnlyPool::FreeAll()
278 {
279     _FX_GrowOnlyTrunk* pTrunk = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
280     while (pTrunk) {
281         _FX_GrowOnlyTrunk* pNext = pTrunk->m_pNext;
282         m_pAllocator->m_Free(m_pAllocator, pTrunk);
283         pTrunk = pNext;
284     }
285     m_pFirstTrunk = NULL;
286 }
287 void* CFX_GrowOnlyPool::Alloc(size_t size)
288 {
289     size = (size + 3) / 4 * 4;
290     _FX_GrowOnlyTrunk* pTrunk = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
291     while (pTrunk) {
292         if (pTrunk->m_Size - pTrunk->m_Allocated >= size) {
293             void* p = (FX_LPBYTE)(pTrunk + 1) + pTrunk->m_Allocated;
294             pTrunk->m_Allocated += size;
295             return p;
296         }
297         pTrunk = pTrunk->m_pNext;
298     }
299     size_t alloc_size = size > m_TrunkSize ? size : m_TrunkSize;
300     pTrunk = (_FX_GrowOnlyTrunk*)m_pAllocator->m_Alloc(m_pAllocator, sizeof(_FX_GrowOnlyTrunk) + alloc_size);
301     pTrunk->m_Size = alloc_size;
302     pTrunk->m_Allocated = size;
303     pTrunk->m_pNext = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
304     m_pFirstTrunk = pTrunk;
305     return pTrunk + 1;
306 }