Grail (C++)  1.3.0
A multi-platform, modular, universal engine for embedding advanced AI in games.
MemoryPool.hh
1 // Copyright QED Software 2023.
2 
3 #ifndef GRAIL_POOL_ALLOCATOR_H
4 #define GRAIL_POOL_ALLOCATOR_H
5 
6 #include "../GrailCore/consts.h"
7 
8 #include <memory>
9 #include <string>
10 #include <type_traits>
11 #include <utility>
12 
13 namespace grail
14 {
15 namespace planner
16 {
17  template <typename T>
18  class Emplacer final
19  {
20  public:
21  Emplacer(typename std::enable_if<std::is_trivially_destructible<T>::value>::type* = 0)
22  {
23  }
24 
25  template <typename... Arguments>
26  T& operator()(void* memoryCell, Arguments&&... arguments)
27  {
28  return *(new(memoryCell) T{std::forward<Arguments>(arguments)...});
29  }
30  };
31 
32  template <>
33  class Emplacer<std::string>
34  {
35  public:
36  template <typename... Arguments>
37  std::string& operator()(void* memoryCell, Arguments&&... arguments)
38  {
39  if(StringLength(std::forward<Arguments>(arguments)...) > consts::MAX_STRING_SIZE)
40  {
41  throw std::bad_alloc{};
42  }
43  return *(new(memoryCell) std::string{std::forward<Arguments>(arguments)...});
44  }
45 
46  private:
47  std::size_t StringLength(const std::string& string) const
48  {
49  return string.size();
50  }
51  };
52 
53  template <>
54  class Emplacer<const std::string>
55  {
56  public:
57  template <typename... Arguments>
58  const std::string& operator()(void* memoryCell, Arguments&&... arguments)
59  {
60  if(StringLength(std::forward<Arguments>(arguments)...) > consts::MAX_STRING_SIZE)
61  {
62  throw std::bad_alloc{};
63  }
64  return *(new(memoryCell) const std::string{std::forward<Arguments>(arguments)...});
65  }
66 
67  private:
68  std::size_t StringLength(const std::string& string) const
69  {
70  return string.size();
71  }
72  };
73 
77  class MemoryPool final
78  {
79  public:
84  MemoryPool(const std::size_t BYTES = 5242880u)
85  : blocks{new char[BYTES]},
86  currentMemoryCell{&blocks[0]},
87  _size{0},
88  BYTES{BYTES}
89  {
90  }
91 
92  ~MemoryPool()
93  {
94  delete[] blocks;
95  }
96 
97  template <typename T, typename... ConstructorArguments>
98  T& Emplace(ConstructorArguments&&... arguments)
99  {
100  std::size_t memoryRequired = sizeof(T);
101  std::size_t alignment = alignof(T);
102  std::size_t leftoverBytes = _size % alignment;
103 
104  if(leftoverBytes > 0)
105  {
106  std::size_t padding = (alignment - leftoverBytes);
107  _size += padding;
108  if(_size < BYTES)
109  {
110  currentMemoryCell = static_cast<char*>(currentMemoryCell) + padding;
111  }
112  }
113 
114  _size += memoryRequired;
115 
116  if(_size > BYTES)
117  {
118  throw std::bad_alloc{};
119  }
120 
121  Emplacer<T> emplacer;
122  T& result = emplacer(currentMemoryCell, std::forward<ConstructorArguments>(arguments)...);
123  currentMemoryCell = static_cast<char*>(currentMemoryCell) + memoryRequired;
124  return result;
125  }
126 
127  std::size_t Size() const
128  {
129  return _size;
130  }
131 
132  void Reset()
133  {
134  currentMemoryCell = &blocks[0];
135  _size = 0;
136  }
137 
138  private:
139  char* const blocks;
140  void* currentMemoryCell;
141  std::size_t _size;
142  const std::size_t BYTES;
143  };
144 }
145 }
146 
147 #endif // GRAIL_POOL_ALLOCATOR_H
grail::planner::Emplacer
Definition: MemoryPool.hh:18
grail::planner::MemoryPool
The MemoryPool class - preallocated memory container for optimization issues.
Definition: MemoryPool.hh:77
grail::planner::MemoryPool::MemoryPool
MemoryPool(const std::size_t BYTES=5242880u)
MemoryPool.
Definition: MemoryPool.hh:84