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