CommonLibSSE (Parapets fork)
MemoryManager.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/S/ScrapHeap.h"
4 
5 namespace RE
6 {
7  namespace CompactingStore
8  {
9  class Store;
10  }
11 
12  class BSSmallBlockAllocator;
13  class IMemoryHeap;
14 
16  {
17  public:
19  {
20  public:
21  // members
22  ScrapHeap heap; // 00
24  std::uint32_t owningThread; // 98
25  std::uint32_t pad; // 9C
26  };
27  static_assert(sizeof(ThreadScrapHeap) == 0xA0);
28 
29  [[nodiscard]] static MemoryManager* GetSingleton();
30  [[nodiscard]] void* Allocate(std::size_t a_size, std::int32_t a_alignment, bool a_alignmentRequired);
31  void Deallocate(void* a_mem, bool a_alignmentRequired);
32  [[nodiscard]] ScrapHeap* GetThreadScrapHeap();
33  [[nodiscard]] void* Reallocate(void* a_oldMem, std::size_t a_newSize, std::int32_t a_alignment, bool a_aligned);
35 
36  // members
37  bool initialized{ false }; // 000
38  std::uint16_t numHeaps{ 0 }; // 002
39  std::uint16_t numPhysicalHeaps{ 0 }; // 004
40  IMemoryHeap** heaps{ nullptr }; // 008
41  bool* allowOtherContextAllocs{ nullptr }; // 010
42  IMemoryHeap* heapsByContext[127]{ nullptr }; // 018
43  ThreadScrapHeap* threadScrapHeap{ nullptr }; // 410
44  IMemoryHeap** physicalHeaps{ nullptr }; // 418
45  IMemoryHeap* bigAllocHeap{ nullptr }; // 420
46  IMemoryHeap* emergencyHeap{ nullptr }; // 428
49  IMemoryHeap* externalHavokAllocator{ nullptr }; // 440
50  bool specialHeaps{ false }; // 448
51  bool allowPoolUse{ true }; // 449
52  std::uint32_t sysAllocBytes{ 0 }; // 44C
53  std::uint32_t mallocBytes{ 0 }; // 450
54  std::uint32_t alignmentForPools{ 4 }; // 450
55  std::uint32_t mainThreadMemoryProblemPassSignal{ 0 }; // 458
56  std::size_t failedAllocationSize{ 0 }; // 460
57  std::uint32_t numMemoryProblemPassesRun{ 0 }; // 468
58  std::size_t timeOfLastMemoryProblemPass{ 0 }; // 470
59  IMemoryHeap* defaultHeap{ nullptr }; // 478
60  };
61  static_assert(sizeof(MemoryManager) == 0x480);
62 
63  void* malloc(std::size_t a_size);
64 
65  template <class T>
66  inline T* malloc(std::size_t a_size)
67  {
68  return static_cast<T*>(malloc(a_size));
69  }
70 
71  template <class T>
72  inline T* malloc()
73  {
74  return malloc<T>(sizeof(T));
75  }
76 
77  void* aligned_alloc(std::size_t a_alignment, std::size_t a_size);
78 
79  template <class T>
80  inline T* aligned_alloc(std::size_t a_alignment, std::size_t a_size)
81  {
82  return static_cast<T*>(aligned_alloc(a_alignment, a_size));
83  }
84 
85  template <class T>
86  inline T* aligned_alloc()
87  {
88  return aligned_alloc<T>(alignof(T), sizeof(T));
89  }
90 
91  void* calloc(std::size_t a_num, std::size_t a_size);
92 
93  template <class T>
94  inline T* calloc(std::size_t a_num, std::size_t a_size)
95  {
96  return static_cast<T*>(calloc(a_num, a_size));
97  }
98 
99  template <class T>
100  inline T* calloc(std::size_t a_num)
101  {
102  return calloc<T>(a_num, sizeof(T));
103  }
104 
105  void* realloc(void* a_ptr, std::size_t a_newSize);
106 
107  template <class T>
108  inline T* realloc(void* a_ptr, std::size_t a_newSize)
109  {
110  return static_cast<T*>(realloc(a_ptr, a_newSize));
111  }
112 
113  void* aligned_realloc(void* a_ptr, std::size_t a_newSize, std::size_t a_alignment);
114 
115  template <class T>
116  inline T* aligned_realloc(void* a_ptr, std::size_t a_newSize, std::size_t a_alignment)
117  {
118  return static_cast<T*>(aligned_realloc(a_ptr, a_newSize, a_alignment));
119  }
120 
121  void free(void* a_ptr);
122 
123  void aligned_free(void* a_ptr);
124 }
125 
126 #define TES_HEAP_REDEFINE_NEW() \
127  [[nodiscard]] inline void* operator new(std::size_t a_count) \
128  { \
129  const auto mem = RE::malloc(a_count); \
130  if (mem) { \
131  return mem; \
132  } else { \
133  stl::report_and_fail("out of memory"sv); \
134  } \
135  } \
136  \
137  [[nodiscard]] inline void* operator new[](std::size_t a_count) \
138  { \
139  const auto mem = RE::malloc(a_count); \
140  if (mem) { \
141  return mem; \
142  } else { \
143  stl::report_and_fail("out of memory"sv); \
144  } \
145  } \
146  \
147  [[nodiscard]] constexpr void* operator new(std::size_t, void* a_ptr) noexcept { return a_ptr; } \
148  [[nodiscard]] constexpr void* operator new[](std::size_t, void* a_ptr) noexcept { return a_ptr; } \
149  [[nodiscard]] constexpr void* operator new(std::size_t, std::align_val_t, void* a_ptr) noexcept { return a_ptr; } \
150  [[nodiscard]] constexpr void* operator new[](std::size_t, std::align_val_t, void* a_ptr) noexcept { return a_ptr; } \
151  \
152  inline void operator delete(void* a_ptr) { RE::free(a_ptr); } \
153  inline void operator delete[](void* a_ptr) { RE::free(a_ptr); } \
154  inline void operator delete(void* a_ptr, std::align_val_t) { RE::aligned_free(a_ptr); } \
155  inline void operator delete[](void* a_ptr, std::align_val_t) { RE::aligned_free(a_ptr); } \
156  inline void operator delete(void* a_ptr, std::size_t) { RE::free(a_ptr); } \
157  inline void operator delete[](void* a_ptr, std::size_t) { RE::free(a_ptr); } \
158  inline void operator delete(void* a_ptr, std::size_t, std::align_val_t) { RE::aligned_free(a_ptr); } \
159  inline void operator delete[](void* a_ptr, std::size_t, std::align_val_t) { RE::aligned_free(a_ptr); }
160 
161 namespace RE
162 {
163  // this class is an implementation detail of operator new[]/delete[]
164  template <class T>
166  {
167  public:
168  using value_type = T;
169  using size_type = std::size_t;
170  using difference_type = std::ptrdiff_t;
172  using const_reference = const value_type&;
173  using pointer = value_type*;
174  using const_pointer = const value_type*;
176  using const_iterator = const value_type*;
177 
178  constexpr SimpleArray() noexcept = default;
179 
180  explicit SimpleArray(size_type a_count) { resize(a_count); }
181 
183  {
184  static_assert(!std::is_trivially_destructible_v<value_type>, "there's no allocation overhead for trivially destructible types");
185  clear();
186  }
187 
189 
190  [[nodiscard]] reference operator[](size_type a_pos) noexcept
191  {
192  assert(a_pos < size());
193  return _data[a_pos];
194  }
195 
196  [[nodiscard]] const_reference operator[](size_type a_pos) const noexcept
197  {
198  assert(a_pos < size());
199  return _data[a_pos];
200  }
201 
202  [[nodiscard]] reference front() noexcept { return operator[](0); }
203  [[nodiscard]] const_reference front() const noexcept { return operator[](0); }
204 
205  [[nodiscard]] reference back() noexcept { return operator[](size() - 1); }
206  [[nodiscard]] const_reference back() const noexcept { return operator[](size() - 1); }
207 
208  [[nodiscard]] pointer data() noexcept { return _data; }
209  [[nodiscard]] const_pointer data() const noexcept { return _data; }
210 
211  [[nodiscard]] iterator begin() noexcept { return _data; }
212  [[nodiscard]] const_iterator begin() const noexcept { return _data; }
213  [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
214 
215  [[nodiscard]] iterator end() noexcept { return _data ? _data + size() : nullptr; }
216  [[nodiscard]] const_iterator end() const noexcept { return _data ? _data + size() : nullptr; }
217  [[nodiscard]] const_iterator cend() const noexcept { return end(); }
218 
219  [[nodiscard]] bool empty() const noexcept { return size() == 0; }
220 
221  [[nodiscard]] size_type size() const noexcept { return _data ? *static_cast<const std::size_t*>(get_head()) : 0; }
222 
223  void clear()
224  {
225  if (_data) {
226  std::destroy_n(data(), size());
227  free(get_head());
228  _data = nullptr;
229  }
230  }
231 
232  void resize(size_type a_count)
233  {
234  const auto oldSize = size();
235  if (oldSize == a_count) {
236  return;
237  }
238 
239  const auto newData = [=]() {
240  auto bytes = sizeof(value_type) * a_count;
241  if constexpr (alignof(value_type) > alignof(std::size_t)) {
242  bytes += sizeof(value_type);
243  } else {
244  bytes += sizeof(std::size_t);
245  }
246 
247  const auto data = malloc<std::size_t>(bytes);
248  *data = a_count;
249 
250  if constexpr (alignof(value_type) > alignof(std::size_t)) {
251  return reinterpret_cast<pointer>(data) + 1;
252  } else {
253  return reinterpret_cast<pointer>(data + 1);
254  }
255  }();
256 
257  if (a_count < oldSize) { // shrink
258  std::uninitialized_move_n(data(), a_count, newData);
259  } else { // grow
260  std::uninitialized_move_n(data(), oldSize, newData);
261  std::uninitialized_default_construct_n(newData + oldSize, a_count - oldSize);
262  }
263 
264  clear();
265  _data = newData;
266  }
267 
268  protected:
269  [[nodiscard]] void* get_head() noexcept
270  {
271  assert(_data != nullptr);
272  if constexpr (alignof(value_type) > alignof(std::size_t)) {
273  return _data - 1;
274  } else {
275  return reinterpret_cast<std::size_t*>(_data) - 1;
276  }
277  }
278 
279  [[nodiscard]] const void* get_head() const noexcept
280  {
281  assert(_data != nullptr);
282  if constexpr (alignof(value_type) > alignof(std::size_t)) {
283  return _data - 1;
284  } else {
285  return reinterpret_cast<const std::size_t*>(_data) - 1;
286  }
287  }
288 
289  // members
290  pointer _data{ nullptr }; // 0
291  };
292 }
Definition: BSSmallBlockAllocator.h:61
Definition: CompactingStore.h:15
Definition: IMemoryHeap.h:31
Definition: MemoryManager.h:16
std::uint16_t numHeaps
Definition: MemoryManager.h:38
BSSmallBlockAllocator * smallBlockAllocator
Definition: MemoryManager.h:47
std::uint32_t mallocBytes
Definition: MemoryManager.h:53
IMemoryHeap * defaultHeap
Definition: MemoryManager.h:59
std::uint32_t numMemoryProblemPassesRun
Definition: MemoryManager.h:57
std::uint16_t numPhysicalHeaps
Definition: MemoryManager.h:39
bool specialHeaps
Definition: MemoryManager.h:50
CompactingStore::Store * compactingStore
Definition: MemoryManager.h:48
std::uint32_t alignmentForPools
Definition: MemoryManager.h:54
ScrapHeap * GetThreadScrapHeap()
void Deallocate(void *a_mem, bool a_alignmentRequired)
std::size_t failedAllocationSize
Definition: MemoryManager.h:56
ThreadScrapHeap * threadScrapHeap
Definition: MemoryManager.h:43
bool allowPoolUse
Definition: MemoryManager.h:51
static MemoryManager * GetSingleton()
std::uint32_t sysAllocBytes
Definition: MemoryManager.h:52
IMemoryHeap ** physicalHeaps
Definition: MemoryManager.h:44
IMemoryHeap ** heaps
Definition: MemoryManager.h:40
IMemoryHeap * bigAllocHeap
Definition: MemoryManager.h:45
void * Reallocate(void *a_oldMem, std::size_t a_newSize, std::int32_t a_alignment, bool a_aligned)
std::uint32_t mainThreadMemoryProblemPassSignal
Definition: MemoryManager.h:55
IMemoryHeap * emergencyHeap
Definition: MemoryManager.h:46
std::size_t timeOfLastMemoryProblemPass
Definition: MemoryManager.h:58
void RegisterMemoryManager()
void * Allocate(std::size_t a_size, std::int32_t a_alignment, bool a_alignmentRequired)
IMemoryHeap * externalHavokAllocator
Definition: MemoryManager.h:49
IMemoryHeap * heapsByContext[127]
Definition: MemoryManager.h:42
bool * allowOtherContextAllocs
Definition: MemoryManager.h:41
bool initialized
Definition: MemoryManager.h:37
Definition: ScrapHeap.h:8
Definition: MemoryManager.h:166
const_iterator begin() const noexcept
Definition: MemoryManager.h:212
const_iterator end() const noexcept
Definition: MemoryManager.h:216
size_type size() const noexcept
Definition: MemoryManager.h:221
value_type & reference
Definition: MemoryManager.h:171
std::size_t size_type
Definition: MemoryManager.h:169
T value_type
Definition: MemoryManager.h:168
void * get_head() noexcept
Definition: MemoryManager.h:269
const_iterator cend() const noexcept
Definition: MemoryManager.h:217
const void * get_head() const noexcept
Definition: MemoryManager.h:279
pointer data() noexcept
Definition: MemoryManager.h:208
iterator begin() noexcept
Definition: MemoryManager.h:211
void clear()
Definition: MemoryManager.h:223
pointer _data
Definition: MemoryManager.h:290
iterator end() noexcept
Definition: MemoryManager.h:215
const value_type & const_reference
Definition: MemoryManager.h:172
~SimpleArray()
Definition: MemoryManager.h:182
reference back() noexcept
Definition: MemoryManager.h:205
value_type * iterator
Definition: MemoryManager.h:175
reference front() noexcept
Definition: MemoryManager.h:202
void resize(size_type a_count)
Definition: MemoryManager.h:232
value_type * pointer
Definition: MemoryManager.h:173
bool empty() const noexcept
Definition: MemoryManager.h:219
const value_type * const_iterator
Definition: MemoryManager.h:176
constexpr SimpleArray() noexcept=default
const_reference front() const noexcept
Definition: MemoryManager.h:203
const_reference operator[](size_type a_pos) const noexcept
Definition: MemoryManager.h:196
const_pointer data() const noexcept
Definition: MemoryManager.h:209
const_iterator cbegin() const noexcept
Definition: MemoryManager.h:213
const_reference back() const noexcept
Definition: MemoryManager.h:206
std::ptrdiff_t difference_type
Definition: MemoryManager.h:170
const value_type * const_pointer
Definition: MemoryManager.h:174
reference operator[](size_type a_pos) noexcept
Definition: MemoryManager.h:190
Definition: AbsorbEffect.h:6
void * realloc(void *a_ptr, std::size_t a_newSize)
Definition: MemoryManager.h:108
void * calloc(std::size_t a_num, std::size_t a_size)
Definition: MemoryManager.h:94
void * malloc(std::size_t a_size)
Definition: MemoryManager.h:66
void * aligned_realloc(void *a_ptr, std::size_t a_newSize, std::size_t a_alignment)
Definition: MemoryManager.h:116
void free(void *a_ptr)
void * aligned_alloc(std::size_t a_alignment, std::size_t a_size)
Definition: MemoryManager.h:80
void aligned_free(void *a_ptr)
Definition: MemoryManager.h:19
ScrapHeap heap
Definition: MemoryManager.h:22
ThreadScrapHeap * next
Definition: MemoryManager.h:23
std::uint32_t owningThread
Definition: MemoryManager.h:24
std::uint32_t pad
Definition: MemoryManager.h:25