Nugget
allocator.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
5 
6 #ifndef EASTL_ALLOCATOR_H
7 #define EASTL_ALLOCATOR_H
8 
9 
10 #include <EASTL/internal/config.h>
11 #include <EABase/nullptr.h>
12 #include <stddef.h>
13 
14 
15 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
16  #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
17 #endif
18 
19 
20 
21 namespace eastl
22 {
23 
29  {
30  MEM_TEMP = 0, // Low memory, not necessarily actually temporary.
31  MEM_PERM = 1 // High memory, for things that won't be unloaded.
32  };
33 
34 
51  class EASTL_API allocator
52  {
53  public:
54  EASTL_ALLOCATOR_EXPLICIT allocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME));
55  allocator(const allocator& x);
56  allocator(const allocator& x, const char* pName);
57 
58  allocator& operator=(const allocator& x);
59 
60  void* allocate(size_t n, int flags = 0);
61  void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);
62  void deallocate(void* p, size_t n);
63 
64  const char* get_name() const;
65  void set_name(const char* pName);
66 
67  protected:
68  #if EASTL_NAME_ENABLED
69  const char* mpName; // Debug name, used to track memory.
70  #endif
71  };
72 
73  bool operator==(const allocator& a, const allocator& b);
74  bool operator!=(const allocator& a, const allocator& b);
75 
76 
77 
82  class EASTL_API dummy_allocator
83  {
84  public:
85  EASTL_ALLOCATOR_EXPLICIT dummy_allocator(const char* = NULL) { }
87  dummy_allocator(const dummy_allocator&, const char*) { }
88 
89  dummy_allocator& operator=(const dummy_allocator&) { return *this; }
90 
91  void* allocate(size_t, int = 0) { return NULL; }
92  void* allocate(size_t, size_t, size_t, int = 0) { return NULL; }
93  void deallocate(void*, size_t) { }
94 
95  const char* get_name() const { return ""; }
96  void set_name(const char*) { }
97  };
98 
99  inline bool operator==(const dummy_allocator&, const dummy_allocator&) { return true; }
100  inline bool operator!=(const dummy_allocator&, const dummy_allocator&) { return false; }
101 
102 
103 
110  EASTL_API allocator* GetDefaultAllocator();
111  EASTL_API allocator* SetDefaultAllocator(allocator* pAllocator);
112 
113 
131  template <typename Allocator>
132  Allocator* get_default_allocator(const Allocator*);
133 
134  EASTLAllocatorType* get_default_allocator(const EASTLAllocatorType*);
135 
136 
142  void* default_allocfreemethod(size_t n, void* pBuffer, void* /*pContext*/);
143 
144 
152  template <typename Allocator>
153  void* allocate_memory(Allocator& a, size_t n, size_t alignment, size_t alignmentOffset);
154 
155 
156 } // namespace eastl
157 
158 
159 
160 
161 
162 
163 #ifndef EASTL_USER_DEFINED_ALLOCATOR // If the user hasn't declared that he has defined a different allocator implementation elsewhere...
164 
165  EA_DISABLE_ALL_VC_WARNINGS()
166  #include <new>
167  EA_RESTORE_ALL_VC_WARNINGS()
168 
169  #if !EASTL_DLL // If building a regular library and not building EASTL as a DLL...
170  // It is expected that the application define the following
171  // versions of operator new for the application. Either that or the
172  // user needs to override the implementation of the allocator class.
173  inline void* operator new[](size_t size, const char* pName, int flags, unsigned debugFlags, const char* file, int line) { return operator new(size); }
174  inline void* operator new[](size_t size, size_t alignment, size_t alignmentOffset, const char* pName, int flags, unsigned debugFlags, const char* file, int line) { return operator new(size); }
175  #endif
176 
177  namespace eastl
178  {
179  inline allocator::allocator(const char* EASTL_NAME(pName))
180  {
181  #if EASTL_NAME_ENABLED
182  mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
183  #endif
184  }
185 
186 
187  inline allocator::allocator(const allocator& EASTL_NAME(alloc))
188  {
189  #if EASTL_NAME_ENABLED
190  mpName = alloc.mpName;
191  #endif
192  }
193 
194 
195  inline allocator::allocator(const allocator&, const char* EASTL_NAME(pName))
196  {
197  #if EASTL_NAME_ENABLED
198  mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
199  #endif
200  }
201 
202 
203  inline allocator& allocator::operator=(const allocator& EASTL_NAME(alloc))
204  {
205  #if EASTL_NAME_ENABLED
206  mpName = alloc.mpName;
207  #endif
208  return *this;
209  }
210 
211 
212  inline const char* allocator::get_name() const
213  {
214  #if EASTL_NAME_ENABLED
215  return mpName;
216  #else
217  return EASTL_ALLOCATOR_DEFAULT_NAME;
218  #endif
219  }
220 
221 
222  inline void allocator::set_name(const char* EASTL_NAME(pName))
223  {
224  #if EASTL_NAME_ENABLED
225  mpName = pName;
226  #endif
227  }
228 
229 
230  inline void* allocator::allocate(size_t n, int flags)
231  {
232  #if EASTL_NAME_ENABLED
233  #define pName mpName
234  #else
235  #define pName EASTL_ALLOCATOR_DEFAULT_NAME
236  #endif
237 
238  #if EASTL_DLL
239  return allocate(n, EASTL_SYSTEM_ALLOCATOR_MIN_ALIGNMENT, 0, flags);
240  #elif (EASTL_DEBUGPARAMS_LEVEL <= 0)
241  return ::new((char*)0, flags, 0, (char*)0, 0) char[n];
242  #elif (EASTL_DEBUGPARAMS_LEVEL == 1)
243  return ::new( pName, flags, 0, (char*)0, 0) char[n];
244  #else
245  return ::new( pName, flags, 0, __FILE__, __LINE__) char[n];
246  #endif
247  }
248 
249 
250  inline void* allocator::allocate(size_t n, size_t alignment, size_t offset, int flags)
251  {
252  #if EASTL_DLL
253  // We currently have no support for implementing flags when
254  // using the C runtime library operator new function. The user
255  // can use SetDefaultAllocator to override the default allocator.
256  EA_UNUSED(offset); EA_UNUSED(flags);
257 
258  size_t adjustedAlignment = (alignment > EA_PLATFORM_PTR_SIZE) ? alignment : EA_PLATFORM_PTR_SIZE;
259 
260  void* p = new char[n + adjustedAlignment + EA_PLATFORM_PTR_SIZE];
261  void* pPlusPointerSize = (void*)((uintptr_t)p + EA_PLATFORM_PTR_SIZE);
262  void* pAligned = (void*)(((uintptr_t)pPlusPointerSize + adjustedAlignment - 1) & ~(adjustedAlignment - 1));
263 
264  void** pStoredPtr = (void**)pAligned - 1;
265  EASTL_ASSERT(pStoredPtr >= p);
266  *(pStoredPtr) = p;
267 
268  EASTL_ASSERT(((size_t)pAligned & ~(alignment - 1)) == (size_t)pAligned);
269 
270  return pAligned;
271  #elif (EASTL_DEBUGPARAMS_LEVEL <= 0)
272  return ::new(alignment, offset, (char*)0, flags, 0, (char*)0, 0) char[n];
273  #elif (EASTL_DEBUGPARAMS_LEVEL == 1)
274  return ::new(alignment, offset, pName, flags, 0, (char*)0, 0) char[n];
275  #else
276  return ::new(alignment, offset, pName, flags, 0, __FILE__, __LINE__) char[n];
277  #endif
278 
279  #undef pName // See above for the definition of this.
280  }
281 
282 
283  inline void allocator::deallocate(void* p, size_t)
284  {
285  #if EASTL_DLL
286  if (p != nullptr)
287  {
288  void* pOriginalAllocation = *((void**)p - 1);
289  delete[](char*)pOriginalAllocation;
290  }
291  #else
292  delete[](char*)p;
293  #endif
294  }
295 
296 
297  inline bool operator==(const allocator&, const allocator&)
298  {
299  return true; // All allocators are considered equal, as they merely use global new/delete.
300  }
301 
302 
303  inline bool operator!=(const allocator&, const allocator&)
304  {
305  return false; // All allocators are considered equal, as they merely use global new/delete.
306  }
307 
308 
309  } // namespace eastl
310 
311 
312 #endif // EASTL_USER_DEFINED_ALLOCATOR
313 
314 
315 
316 namespace eastl
317 {
318 
319  template <typename Allocator>
320  inline Allocator* get_default_allocator(const Allocator*)
321  {
322  return NULL; // By default we return NULL; the user must make specialization of this function in order to provide their own implementation.
323  }
324 
325 
326  inline EASTLAllocatorType* get_default_allocator(const EASTLAllocatorType*)
327  {
328  return EASTLAllocatorDefault(); // For the built-in allocator EASTLAllocatorType, we happen to already have a function for returning the default allocator instance, so we provide it.
329  }
330 
331 
332  inline void* default_allocfreemethod(size_t n, void* pBuffer, void* /*pContext*/)
333  {
334  EASTLAllocatorType* const pAllocator = EASTLAllocatorDefault();
335 
336  if(pBuffer) // If freeing...
337  {
338  EASTLFree(*pAllocator, pBuffer, n);
339  return NULL; // The return value is meaningless for the free.
340  }
341  else // allocating
342  return EASTLAlloc(*pAllocator, n);
343  }
344 
345 
353  template <typename Allocator>
354  inline void* allocate_memory(Allocator& a, size_t n, size_t alignment, size_t alignmentOffset)
355  {
356  void *result;
357  if (alignment <= EASTL_ALLOCATOR_MIN_ALIGNMENT)
358  {
359  result = EASTLAlloc(a, n);
360  // Ensure the result is correctly aligned. An assertion likely indicates a mismatch between EASTL_ALLOCATOR_MIN_ALIGNMENT and the minimum alignment
361  // of EASTLAlloc. If there is a mismatch it may be necessary to define EASTL_ALLOCATOR_MIN_ALIGNMENT to be the minimum alignment of EASTLAlloc, or
362  // to increase the alignment of EASTLAlloc to match EASTL_ALLOCATOR_MIN_ALIGNMENT.
363  EASTL_ASSERT((reinterpret_cast<size_t>(result)& ~(alignment - 1)) == reinterpret_cast<size_t>(result));
364  }
365  else
366  {
367  result = EASTLAllocAligned(a, n, alignment, alignmentOffset);
368  // Ensure the result is correctly aligned. An assertion here may indicate a bug in the allocator.
369  auto resultMinusOffset = (char*)result - alignmentOffset;
370  EA_UNUSED(resultMinusOffset);
371  EASTL_ASSERT((reinterpret_cast<size_t>(resultMinusOffset)& ~(alignment - 1)) == reinterpret_cast<size_t>(resultMinusOffset));
372  }
373  return result;
374  }
375 
376 }
377 
378 
379 #endif // Header include guard
380 
381 
382 
383 
384 
385 
386 
387 
388 
389 
390 
391 
392 
393 
394 
395 
Definition: allocator.h:52
Definition: allocator.h:83
EA Standard Template Library.
Definition: algorithm.h:288
alloc_flags
Definition: allocator.h:29
Allocator * get_default_allocator(const Allocator *)
Definition: allocator.h:320
EASTL_API allocator * GetDefaultAllocator()
Definition: allocator_eastl.cpp:30
void * allocate_memory(Allocator &a, size_t n, size_t alignment, size_t alignmentOffset)
Definition: allocator.h:354
void * default_allocfreemethod(size_t n, void *pBuffer, void *)
Definition: allocator.h:332