Nugget
fixed_allocator.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
6 // This file implements the following
7 // fixed_allocator
8 // fixed_allocator_with_overflow
10 
11 
12 #ifndef EASTL_FIXED_ALLOCATOR_H
13 #define EASTL_FIXED_ALLOCATOR_H
14 
15 
16 #include <EASTL/internal/config.h>
17 #include <EASTL/internal/fixed_pool.h>
18 #include <EASTL/functional.h>
19 #include <EASTL/memory.h>
20 #include <EASTL/allocator.h>
21 #include <EASTL/type_traits.h>
22 
23 EA_DISABLE_ALL_VC_WARNINGS();
24 
25 #include <new>
26 
27 EA_RESTORE_ALL_VC_WARNINGS();
28 
29 EA_DISABLE_VC_WARNING(4275); // non dll-interface class used as base for DLL-interface classkey 'identifier'
30 
31 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
32  #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.
33 #endif
34 
35 
36 
37 namespace eastl
38 {
39 
41  // fixed_allocator
43 
83  class EASTL_API fixed_allocator : public fixed_pool_base
84  {
85  public:
91  fixed_allocator(const char* /*pName*/ = EASTL_FIXED_POOL_DEFAULT_NAME)
92  : fixed_pool_base(NULL)
93  {
94  }
95 
96 
105  : fixed_pool_base(NULL)
106  {
107  }
108 
109 
117  {
118  return *this;
119  }
120 
121 
122  // init
123  //
124  // No init here, as the base class version is sufficient.
125  //
126  //void init(void* pMemory, size_t memorySize, size_t nodeSize,
127  // size_t alignment, size_t alignmentOffset = 0);
128 
129 
135  void* allocate(size_t n, int /*flags*/ = 0)
136  {
137  // To consider: Verify that 'n' is what the user initialized us with.
138 
139  Link* pLink = mpHead;
140 
141  if(pLink) // If we have space...
142  {
143  #if EASTL_FIXED_SIZE_TRACKING_ENABLED
144  if(++mnCurrentSize > mnPeakSize)
145  mnPeakSize = mnCurrentSize;
146  #endif
147 
148  mpHead = pLink->mpNext;
149  return pLink;
150  }
151  else
152  {
153  // If there's no free node in the free list, just
154  // allocate another from the reserved memory area
155 
156  if(mpNext != mpCapacity)
157  {
158  pLink = mpNext;
159 
160  mpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + n);
161 
162  #if EASTL_FIXED_SIZE_TRACKING_ENABLED
163  if(++mnCurrentSize > mnPeakSize)
164  mnPeakSize = mnCurrentSize;
165  #endif
166 
167  return pLink;
168  }
169 
170  // EASTL_ASSERT(false); To consider: enable this assert. However, we intentionally disable it because this isn't necessarily an assertable error.
171  return NULL;
172  }
173  }
174 
175 
178  void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)
179  {
180  return allocate(n, flags);
181  }
182 
183 
190  void deallocate(void* p, size_t)
191  {
192  #if EASTL_FIXED_SIZE_TRACKING_ENABLED
193  --mnCurrentSize;
194  #endif
195 
196  ((Link*)p)->mpNext = mpHead;
197  mpHead = ((Link*)p);
198  }
199 
200 
202 
203 
204  const char* get_name() const
205  {
206  return EASTL_FIXED_POOL_DEFAULT_NAME;
207  }
208 
209 
210  void set_name(const char*)
211  {
212  // Nothing to do. We don't allocate memory.
213  }
214 
215  }; // fixed_allocator
216 
217  bool operator==(const fixed_allocator& a, const fixed_allocator& b);
218  bool operator!=(const fixed_allocator& a, const fixed_allocator& b);
219 
220 
221 
223  // fixed_allocator_with_overflow
225 
262  {
263  public:
269  fixed_allocator_with_overflow(const char* pName = EASTL_FIXED_POOL_DEFAULT_NAME)
270  : fixed_pool_base(NULL)
271  , mOverflowAllocator(pName)
272  , mpPoolBegin(nullptr)
273  , mpPoolEnd(nullptr)
274  , mnNodeSize(0)
275  {
276  }
277 
278 
287  : fixed_pool_base(NULL)
288  , mpPoolBegin(nullptr)
289  , mpPoolEnd(nullptr)
290  , mnNodeSize(0)
291  {
292  }
293 
294 
302  {
303  #if EASTL_ALLOCATOR_COPY_ENABLED
304  mOverflowAllocator = x.mOverflowAllocator;
305  #else
306  (void)x;
307  #endif
308 
309  return *this;
310  }
311 
312 
315  void init(void* pMemory, size_t memorySize, size_t nodeSize,
316  size_t alignment, size_t alignmentOffset = 0)
317  {
318  fixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset);
319 
320  mpPoolBegin = pMemory;
321  mpPoolEnd = (void*)((uintptr_t)pMemory + memorySize);
322  mnNodeSize = (eastl_size_t)nodeSize;
323  }
324 
325 
331  void* allocate(size_t /*n*/, int /*flags*/ = 0)
332  {
333  // To consider: Verify that 'n' is what the user initialized us with.
334 
335  void* p;
336 
337  if(mpHead) // If we have space...
338  {
339  p = mpHead;
340  mpHead = mpHead->mpNext;
341  }
342  else
343  {
344  // If there's no free node in the free list, just
345  // allocate another from the reserved memory area
346 
347  if (mpNext != mpCapacity)
348  {
349  p = mpNext;
350  mpNext = reinterpret_cast<Link*>(reinterpret_cast<char*>(mpNext) + mnNodeSize);
351  }
352  else
353  p = mOverflowAllocator.allocate(mnNodeSize);
354  }
355 
356  #if EASTL_FIXED_SIZE_TRACKING_ENABLED
357  if(p && (++mnCurrentSize > mnPeakSize))
358  mnPeakSize = mnCurrentSize;
359  #endif
360 
361  return p;
362  }
363 
364 
367  void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0)
368  {
369  return allocate(n, flags);
370  }
371 
372 
379  void deallocate(void* p, size_t)
380  {
381  #if EASTL_FIXED_SIZE_TRACKING_ENABLED
382  --mnCurrentSize;
383  #endif
384 
385  if((p >= mpPoolBegin) && (p < mpPoolEnd))
386  {
387  ((Link*)p)->mpNext = mpHead;
388  mpHead = ((Link*)p);
389  }
390  else
391  mOverflowAllocator.deallocate(p, (size_t)mnNodeSize);
392  }
393 
394 
396 
397 
398  const char* get_name() const
399  {
400  return mOverflowAllocator.get_name();
401  }
402 
403 
404  void set_name(const char* pName)
405  {
406  mOverflowAllocator.set_name(pName);
407  }
408 
409  protected:
410  EASTLAllocatorType mOverflowAllocator; // To consider: Allow the user to define the type of this, presumably via a template parameter.
411  void* mpPoolBegin; // To consider: We have these member variables and ideally we shouldn't need them. The problem is that
412  void* mpPoolEnd; // the information about the pool buffer and object size is stored in the owning container
413  eastl_size_t mnNodeSize; // and we can't have access to it without increasing the amount of code we need and by templating
414  // more code. It may turn out that simply storing data here is smaller in the end.
415  }; // fixed_allocator_with_overflow // Granted, this class is usually used for debugging purposes, but perhaps there is an elegant solution.
416 
417  bool operator==(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);
418  bool operator!=(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b);
419 
420 
421 
422 
423 
424 
426  // global operators
428 
429  inline bool operator==(const fixed_allocator&, const fixed_allocator&)
430  {
431  return false;
432  }
433 
434  inline bool operator!=(const fixed_allocator&, const fixed_allocator&)
435  {
436  return false;
437  }
438 
439  inline bool operator==(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)
440  {
441  return false;
442  }
443 
444  inline bool operator!=(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&)
445  {
446  return false;
447  }
448 
449 
450 } // namespace eastl
451 
452 
453 EA_RESTORE_VC_WARNING();
454 
455 #endif // Header include guard
Definition: fixed_allocator.h:262
void deallocate(void *p, size_t)
Definition: fixed_allocator.h:379
fixed_allocator_with_overflow(const fixed_allocator_with_overflow &)
Definition: fixed_allocator.h:286
void * allocate(size_t, int=0)
Definition: fixed_allocator.h:331
fixed_allocator_with_overflow & operator=(const fixed_allocator_with_overflow &x)
Definition: fixed_allocator.h:301
void * allocate(size_t n, size_t, size_t, int flags=0)
Definition: fixed_allocator.h:367
void init(void *pMemory, size_t memorySize, size_t nodeSize, size_t alignment, size_t alignmentOffset=0)
Definition: fixed_allocator.h:315
fixed_allocator_with_overflow(const char *pName=EASTL_FIXED_POOL_DEFAULT_NAME)
Definition: fixed_allocator.h:269
Definition: fixed_allocator.h:84
fixed_allocator & operator=(const fixed_allocator &)
Definition: fixed_allocator.h:116
void * allocate(size_t n, size_t, size_t, int flags=0)
Definition: fixed_allocator.h:178
void deallocate(void *p, size_t)
Definition: fixed_allocator.h:190
fixed_allocator(const char *=EASTL_FIXED_POOL_DEFAULT_NAME)
Definition: fixed_allocator.h:91
fixed_allocator(const fixed_allocator &)
Definition: fixed_allocator.h:104
void * allocate(size_t n, int=0)
Definition: fixed_allocator.h:135
EA Standard Template Library.
Definition: algorithm.h:288
Definition: fixed_pool.h:134
bool can_allocate() const
Definition: fixed_pool.h:200
EASTL_API void init(void *pMemory, size_t memorySize, size_t nodeSize, size_t alignment, size_t alignmentOffset=0)
Definition: fixed_pool.cpp:15