CppCommon  1.0.4.1
C++ Common Library
allocator.inl
Go to the documentation of this file.
1 
9 #if defined(_MSC_VER)
10 #pragma warning(push)
11 #pragma warning(disable: 4127) // C4127: conditional expression is constant
12 #endif
13 
14 namespace CppCommon {
15 
16 template <typename T, typename U, class TMemoryManager, bool nothrow>
18 {
19  return true;
20 }
21 
22 template <typename T, typename U, class TMemoryManager, bool nothrow>
24 {
25  return false;
26 }
27 
28 template <typename T, class TMemoryManager, bool nothrow>
29 inline T* Allocator<T, TMemoryManager, nothrow>::allocate(size_t num, const void* hint)
30 {
31  pointer result = (pointer)_manager.malloc(num * sizeof(T), alignof(T));
32  if (result != nullptr)
33  return result;
34 
35  // Not enough memory...
36  if (nothrow)
37  return nullptr;
38  else
39  throw std::bad_alloc();
40 }
41 
42 template <typename T, class TMemoryManager, bool nothrow>
44 {
45  _manager.free(ptr, num * sizeof(T));
46 }
47 
48 template <typename T, class TMemoryManager, bool nothrow>
49 template <typename U, class... Args>
50 inline void Allocator<T, TMemoryManager, nothrow>::construct(U* ptr, Args&&... args)
51 {
52  assert((ptr != nullptr) && "Constructed element must be valid!");
53 
54  // Construct the element
55  if (ptr != nullptr)
56  new ((void*)ptr) U(std::forward<Args>(args)...);
57 }
58 
59 template <typename T, class TMemoryManager, bool nothrow>
60 template <typename U>
62 {
63  assert((ptr != nullptr) && "Destroyed element must be valid!");
64 
65  // Destroy the element
66  if (ptr != nullptr)
67  ptr->~U();
68 }
69 
70 template <typename T, class TMemoryManager, bool nothrow>
71 template <class... Args>
73 {
74  // Allocate memory for the element
75  void* ptr = _manager.malloc(sizeof(T));
76 
77  // Construct the element
78  if (ptr != nullptr)
79  new (ptr) T(std::forward<Args>(args)...);
80 
81  return (T*)ptr;
82 }
83 
84 template <typename T, class TMemoryManager, bool nothrow>
86 {
87  assert((ptr != nullptr) && "Released element must be valid!");
88 
89  // Release the element
90  if (ptr != nullptr)
91  {
92  // Destroy the element
93  ptr->~T();
94 
95  // Free element memory
96  _manager.free(ptr, sizeof(T));
97  }
98 }
99 
100 template <typename T, class TMemoryManager, bool nothrow>
101 template <class... Args>
102 inline T* Allocator<T, TMemoryManager, nothrow>::CreateArray(size_t length, Args&&... args)
103 {
104  assert((length > 0) && "Array length must be greater than zero!");
105 
106  size_t header = sizeof(size_t) / sizeof(T);
107  if ((sizeof(size_t) % sizeof(T)) > 0)
108  header += 1;
109 
110  // Allocate extra space to store array length in the bytes before the array
111  T* ptr = ((T*)_manager.malloc(sizeof(T) * (length + header), alignof(T))) + header;
112 
113  // Store the array length value
114  *(((size_t*)ptr) - 1) = length;
115 
116  // Construct array elements
117  for (size_t i = 0; i < length; ++i)
118  new (&ptr[i]) T(std::forward<Args>(args)...);
119 
120  return ptr;
121 }
122 
123 template <typename T, class TMemoryManager, bool nothrow>
125 {
126  assert((ptr != nullptr) && "Released array must be valid!");
127 
128  // Release the array
129  if (ptr != nullptr)
130  {
131  // Get the length of the array
132  size_t length = *(((size_t*)ptr) - 1);
133 
134  // Destroy array elements
135  for(size_t i = 0; i < length; ++i)
136  ptr[i].~T();
137 
138  // Calculate how much extra memory was allocated to store the length before the array
139  size_t header = sizeof(size_t) / sizeof(T);
140  if ((sizeof(size_t) % sizeof(T)) > 0)
141  header += 1;
142 
143  // Free array memory
144  _manager.free(ptr - header, sizeof(T) * (length + header));
145  }
146 }
147 
148 inline void* DefaultMemoryManager::malloc(size_t size, size_t alignment)
149 {
150  assert((size > 0) && "Allocated block size must be greater than zero!");
151  assert(Memory::IsValidAlignment(alignment) && "Alignment must be valid!");
152 
153  void* result = std::malloc(size);
154  if (result != nullptr)
155  {
156  // Update allocation statistics
157  _allocated += size;
158  ++_allocations;
159  }
160  return result;
161 }
162 
163 inline void DefaultMemoryManager::free(void* ptr, size_t size)
164 {
165  assert((ptr != nullptr) && "Deallocated block must be valid!");
166 
167  if (ptr != nullptr)
168  {
169  std::free(ptr);
170 
171  // Update allocation statistics
172  _allocated -= size;
173  --_allocations;
174  }
175 }
176 
178 {
179  assert((_allocated == 0) && "Memory leak detected! Allocated memory size must be zero!");
180  assert((_allocations == 0) && "Memory leak detected! Count of active memory allocations must be zero!");
181 }
182 
183 } // namespace CppCommon
184 
185 #if defined(_MSC_VER)
186 #pragma warning(pop)
187 #endif
Memory allocator class.
Definition: allocator.h:25
void construct(U *ptr, Args &&... args)
Constructs an element object on the given location pointer.
Definition: allocator.inl:50
void ReleaseArray(T *ptr)
Release an array of element objects.
Definition: allocator.inl:124
void Release(T *ptr)
Release a single element object.
Definition: allocator.inl:85
T * CreateArray(size_t length, Args &&... args)
Create an array of element objects.
Definition: allocator.inl:102
void deallocate(pointer ptr, size_type num)
Release a block of storage previously allocated.
Definition: allocator.inl:43
T * Create(Args &&... args)
Create a single element object.
Definition: allocator.inl:72
T * pointer
Pointer to element.
Definition: allocator.h:33
pointer allocate(size_type num, const void *hint=0)
Allocate a block of storage suitable to contain the given count of elements.
Definition: allocator.inl:29
void destroy(U *ptr)
Destroys in-place the object pointed by the given location pointer.
Definition: allocator.inl:61
void free(void *ptr, size_t size)
Free the previously allocated memory block.
Definition: allocator.inl:163
void reset()
Reset the memory manager.
Definition: allocator.inl:177
void * malloc(size_t size, size_t alignment=alignof(std::max_align_t))
Allocate a new memory block of the given size.
Definition: allocator.inl:148
static bool IsValidAlignment(size_t alignment) noexcept
Is the given alignment valid?
Definition: memory.inl:13
C++ Common project definitions.
Definition: token_bucket.h:15
bool operator==(const uint128_t &value1, const uint128_t &value2) noexcept
Definition: uint128.inl:115
bool operator!=(const uint128_t &value1, const uint128_t &value2) noexcept
Definition: uint128.inl:120