MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
alloc.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef MAIA_ALLOC_H
8#define MAIA_ALLOC_H
13#include <vector>
14#include "INCLUDE/maiatypes.h"
15#include "IO/infoout.h"
16#include "collector.h"
17#include "genericobject.h"
18#include "globalvariables.h"
19#include "list.h"
21template <class T>
22class Collector; // Forward declaration
24
25namespace maia {
26namespace alloc {
27
29#ifdef MAIA_EXTRA_DEBUG
30
31inline void debug(const MString& objectName, const MString& elementsName) {
32 MString allocatedObjectName = (objectName == elementsName) ? objectName : objectName + elementsName;
33 typedef std::vector<GenericObject*>::iterator GenericObjIt;
34 for(GenericObjIt i = g_allocatedObjects.begin(); i != g_allocatedObjects.end(); i++) {
35 if((*i)->getName() == allocatedObjectName) {
36 std::cerr << "Warning: object " << objectName << " has already been allocated!" << std::endl;
37 m_log << "Warning: object " << objectName << " has already been allocated!" << std::endl;
38 }
39 }
40}
41inline void debug(const MString& objectName) { debug(objectName, objectName); }
42inline void debug_collector(const MString& objectName, const MInt maxSize, const MString& function) {
43 debug(objectName);
44 m_log << "Creating collector '" << objectName << "' with " << maxSize << " elements as requested by " << function
45 << "." << std::endl;
46}
47
48inline void debug_list(const MString& objectName, const MInt maxSize, const MString& function) {
49 debug(objectName);
50 m_log << "Creating list '" << objectName << "' with " << maxSize << " elements as requested by " << function << "."
51 << std::endl;
52}
53#else
54inline void debug(const MString&, const MString&) {}
55inline void debug(const MString&) {}
56inline void debug_collector(const MString&, const MInt, const MString&) {}
57inline void debug_list(const MString&, const MInt, const MString&) {}
58#endif
59
60
62template <class T>
63inline MInt findAllocatedObject(const T* const a, std::vector<GenericObject*>::iterator& hit) {
64 if(a == nullptr) {
65 return 0;
66 }
67
68 MInt count = 0;
69 for(auto i = g_allocatedObjects.begin(); i != g_allocatedObjects.end(); i++) {
70 auto* object = static_cast<GenericPointer<T>*>(*i);
71 if(static_cast<T*>((*object).getObjectPointer()) == a) {
72 count++;
73 hit = i;
74 if((*object).objectIsArray) {
75 auto j = i + 1;
76 while((j != g_allocatedObjects.end()) && ((*j)->getObjectId() == (*i)->getObjectId())) {
77 count++;
78 j++;
79 }
80 }
81 break;
82 }
83 }
84 return count;
85}
86
87
89template <class T>
90inline MBool isAllocated(const T* const a) {
91 std::vector<GenericObject*>::iterator hit;
92 const MInt count = findAllocatedObject(a, hit);
93 return (count > 0);
94}
95
96
97#ifdef MAIA_DEBUG_ALLOC
98template <class T>
99inline void checkPointer(const T* const a, const MString objectName, const MString function) {
100 if(isAllocated(a)) {
101 std::cerr << "Warning in mAlloc: pointer for object '" << objectName
102 << "' already in list of allocated objects, call mDeallocate before reallocating! " << function
103 << std::endl;
104 } else if(a != nullptr) {
105 std::cerr << "Warning in mAlloc: passed pointer != nullptr for object '" << objectName << "'! " << function
106 << std::endl;
107 }
108}
109#else
110template <class T>
111inline void checkPointer(const T* const, const MString&, const MString&) {}
112#endif
113
114
115template <class T>
116inline void store_collector(Collector<T>* a, MLong maxSize, const MString& objectName, const MString& functionName) {
117 const MLong size = (T::staticElementSize() * (maxSize + 2) * sizeof(char)) + ((maxSize + 1) * sizeof(T));
118 g_allocatedObjects.push_back(new GenericPointer<Collector<T>>(a, objectName, size, functionName, false));
119}
120
121// This should just be this:
122// template<class T, class... Us> inline Collector<T>* make_collector( const Us... us ) {
123// return new Collector<T>(std::forward<Us>(us)...);
124// }
125// But in C++03 we need to do this (although it can be done nicer with a trait...):
126template <class T>
127inline Collector<T>* make_collector(const MLong size, const MInt dummy1, const MInt dummy2, const MInt dummy3,
128 const MInt dummy4) {
129 return new Collector<T>(size, dummy1, dummy2, dummy3, dummy4);
130}
131template <class T>
132inline Collector<T>* make_collector(const MLong size, const MInt dimension, const MFloat dummy, const MInt maxNoSets) {
133 return new Collector<T>(size, dimension, dummy, maxNoSets);
134}
135// Used to allocate:
136// - DG: m_surfaces
137template <class T>
138inline Collector<T>* make_collector(const MLong size, const MInt dimension, const MInt dummy, const MInt dummy1) {
139 return new Collector<T>(size, dimension, dummy, dummy1);
140}
141template <class T>
142inline Collector<T>* make_collector(const MLong size, const MInt dimension, const MInt distributions,
143 const MInt distributions1, const MInt maxNoSurfaces, const MInt dummy1) {
144 return new Collector<T>(size, dimension, distributions, distributions1, maxNoSurfaces, dummy1);
145}
146// Used to allocate:
147// - DG: m_elements
148template <class T>
149inline Collector<T>* make_collector(const MLong size, const MInt dimension, const MInt distributions) {
150 return new Collector<T>(size, dimension, distributions);
151}
152template <class T>
153inline Collector<T>* make_collector(const MLong size, const MInt dimension) {
154 return new Collector<T>(size, dimension);
155}
156template <class T>
157inline Collector<T>* make_collector(const MLong size) {
158 return new Collector<T>(size);
159}
160
161} // namespace alloc
162} // namespace maia
163
166
172template <class T>
173void mAlloc(T*& a, const MLong N, const MString& objectName, MString function) {
174 using namespace maia::alloc;
175 maia::alloc::debug(objectName);
176 maia::alloc::checkPointer(a, objectName, function);
177
178#ifdef MAIA_ASSERT_ALLOC
179 ASSERT(N > 0, "Error in mAlloc: size must be >0, is " + std::to_string(N) + " for " + objectName + " allocated in "
180 + function);
181#endif
182
183 if(N <= 0) {
184#ifdef MAIA_DEBUG_ALLOC
185 std::cerr << "Warning in mAlloc: size should be >0, is " << std::to_string(N) << " for " << objectName
186 << " allocated in " << function << std::endl;
187#endif
188 return;
189 }
190
191 a = new T[N];
192 g_allocatedObjects.push_back(new GenericPointer<T>(a, objectName, N * sizeof(T), function, true));
193}
194
200template <class T>
201void mAlloc(T*& a, const MLong N, const MString& objectName, const T initialValue, MString function) {
202 mAlloc(a, N, objectName, function);
203#ifndef SKIP_INITIAL_VALUE_ALLOC
204 for(MInt i = 0; i < N; i++)
205 a[i] = initialValue;
206#endif
207}
208
214template <class T>
215void mAlloc(T**& a, const MLong N, const MLong M, const MString& objectName, const T initialValue, MString function) {
216 using namespace maia::alloc;
217 maia::alloc::debug(objectName);
218 maia::alloc::checkPointer(a, objectName, function);
219
220#ifdef MAIA_ASSERT_ALLOC
221 ASSERT(N > 0 && M > 0, "Error in mAlloc: sizes must be >0, but they are " + std::to_string(N) + " and "
222 + std::to_string(M) + " for " + objectName + " allocated in " + function);
223#endif
224
225 if(N <= 0 || M <= 0) {
226#ifdef MAIA_DEBUG_ALLOC
227 std::cerr << "Error in mAlloc: sizes should be >0, but they are " << std::to_string(N) << " and "
228 << std::to_string(M) << " for " << objectName << " allocated in " << function << std::endl;
229#endif
230 return;
231 }
232
233 a = new T*[N];
234 g_allocatedObjects.push_back(new GenericPointer<T*>(a, objectName, N * sizeof(T*), function, true));
235
236 const MString elementsName = "_elements";
237 maia::alloc::debug(objectName, elementsName);
238
239 T* dummy = new T[N * M];
240 g_allocatedObjects.push_back(
241 new GenericPointer<T>(dummy, objectName + elementsName, N * M * sizeof(T), function, true, false));
242
243 for(MInt i = 0; i < N; i++) {
244 a[i] = (T*)(&(dummy[M * i]));
245 }
246
247#ifndef SKIP_INITIAL_VALUE_ALLOC
248 for(MInt i = 0; i < N * M; i++)
249 dummy[i] = initialValue;
250#endif
251}
252
253
259template <class T>
260void mAlloc(T**& a, const MLong N, const MLong M, const MString& objectName, MString function) {
261 using namespace maia::alloc;
262 maia::alloc::debug(objectName);
263 maia::alloc::checkPointer(a, objectName, function);
264
265#ifdef MAIA_ASSERT_ALLOC
266 ASSERT(N > 0 && M > 0, "Error in mAlloc: sizes must be >0, but they are " + std::to_string(N) + " and "
267 + std::to_string(M) + " for " + objectName + " allocated in " + function);
268#endif
269
270 if(N <= 0 || M <= 0) {
271#ifdef MAIA_DEBUG_ALLOC
272 std::cerr << "Error in mAlloc: sizes should be >0, but they are " << std::to_string(N) << " and "
273 << std::to_string(M) << " for " << objectName << " allocated in " << function << std::endl;
274#endif
275 return;
276 }
277
278 a = new T*[N];
279
280 g_allocatedObjects.push_back(new GenericPointer<T*>(a, objectName, N * sizeof(T*), function, true));
281
282 const MString elementsName = "[0]";
283 maia::alloc::debug(objectName, elementsName);
284
285 a[0] = new T[N * M];
286 g_allocatedObjects.push_back(
287 new GenericPointer<T>(a[0], objectName + elementsName, N * M * sizeof(T), function, true, false));
288
289 for(MInt i = 1; i < N; i++) {
290 a[i] = (T*)(&(a[0][M * i]));
291 }
292}
293
294
300template <class T>
301void mAlloc(T**& a, const MLong N, const MInt* arraySizes, const MString& objectName, MString function) {
302 using namespace maia::alloc;
303 maia::alloc::debug(objectName);
304 maia::alloc::checkPointer(a, objectName, function);
305
306 size_t size = 0;
307 for(MInt k = 0; k < N; k++) {
308 size += arraySizes[k];
309 }
310
311#ifdef MAIA_ASSERT_ALLOC
312 ASSERT(N > 0 && size > 0, "Error in mAlloc: sizes must be >0, but they are " + std::to_string(N) + " and "
313 + std::to_string(size) + " for " + objectName + " allocated in " + function);
314#endif
315
316 if(N <= 0 || size <= 0) {
317#ifdef MAIA_DEBUG_ALLOC
318 std::cerr << "Error in mAlloc: sizes should be >0, but they are " << std::to_string(N) << " and "
319 << std::to_string(size) << " for " << objectName << " allocated in " << function << std::endl;
320#endif
321 return;
322 }
323
324 a = new T*[N];
325 g_allocatedObjects.push_back(new GenericPointer<T*>(a, objectName, N * sizeof(T*), function, true));
326
327 const MString elementsName = "_elements";
328 maia::alloc::debug(objectName, elementsName);
329
330 T* dummy = new T[size];
331 g_allocatedObjects.push_back(
332 new GenericPointer<T>(dummy, objectName + elementsName, size * sizeof(T), function, true, false));
333
334 size_t cnt = 0;
335 for(MInt i = 0; i < N; i++) {
336 a[i] = (T*)(&(dummy[cnt]));
337 cnt += arraySizes[i];
338 }
339}
340
341
348template <class T>
349void mAlloc(T**& a, const MLong N, const MInt* const arraySizes, MInt factor, const MString& objectName,
350 MString function) {
351 using namespace maia::alloc;
352 maia::alloc::debug(objectName);
353 maia::alloc::checkPointer(a, objectName, function);
354
355 size_t size = 0;
356 for(MInt k = 0; k < N; k++) {
357 size += factor * arraySizes[k];
358 }
359
360#ifdef MAIA_ASSERT_ALLOC
361 ASSERT(N > 0 && size > 0, "Error in mAlloc: sizes must be >0, but they are " + std::to_string(N) + " and "
362 + std::to_string(size) + " for " + objectName + " allocated in " + function);
363#endif
364
365 if(N <= 0 || size <= 0) {
366#ifdef MAIA_DEBUG_ALLOC
367 std::cerr << "Error in mAlloc: sizes should be >0, but they are " << std::to_string(N) << " and "
368 << std::to_string(size) << " for " << objectName << " allocated in " << function << std::endl;
369#endif
370 return;
371 }
372
373 a = new T*[N];
374 g_allocatedObjects.push_back(new GenericPointer<T*>(a, objectName, N * sizeof(T*), function, true));
375
376 const MString elementsName = "_elements";
377 maia::alloc::debug(objectName, elementsName);
378
379 T* dummy = new T[size];
380 g_allocatedObjects.push_back(
381 new GenericPointer<T>(dummy, objectName + elementsName, size * sizeof(T), function, true, false));
382
383 size_t cnt = 0;
384 for(MInt i = 0; i < N; i++) {
385 a[i] = (T*)(&(dummy[cnt]));
386 cnt += factor * arraySizes[i];
387 }
388}
389
390
396template <class T>
397void mAlloc(List<T>*& a, const MLong N, const MString& objectName, const T initialValue, MString function) {
398 using namespace maia::alloc;
399 maia::alloc::debug_list(objectName, N, function);
400 maia::alloc::checkPointer(a, objectName, function);
401
402#ifdef MAIA_ASSERT_ALLOC
403 ASSERT(N > 0, "Error in mAlloc: size must be >0, is " + std::to_string(N) + " for " + objectName + " allocated in "
404 + function);
405#endif
406
407 if(N <= 0) {
408#ifdef MAIA_DEBUG_ALLOC
409 std::cerr << "Warning in mAlloc: size should be >0, is " << std::to_string(N) << " for " << objectName
410 << " allocated in " << function << std::endl;
411#endif
412 return;
413 }
414
415 a = new List<T>(N);
416
417 g_allocatedObjects.push_back(new GenericPointer<List<T>>(a, objectName, N * sizeof(T), function, false));
418
419#ifndef SKIP_INITIAL_VALUE_ALLOC
420 for(MInt i = 0; i < N; i++)
421 a->a[i] = initialValue;
422#endif
423}
424
425
431template <class T>
432void mAlloc(Collector<T>*& a, MLong maxSize, MInt dummy1, MInt dummy2, MInt dummy3, MInt dummy4,
433 const MString& objectName, MString function) {
434 maia::alloc::checkPointer(a, objectName, function);
435 maia::alloc::debug_collector(objectName, maxSize, function);
436 a = maia::alloc::make_collector<T>(maxSize, dummy1, dummy2, dummy3, dummy4);
437 maia::alloc::store_collector(a, maxSize, objectName, function);
438}
439
440
446template <class T>
447void mAlloc(Collector<T>*& a, MLong maxSize, MInt dimension, MFloat dummy, MInt maxNoSets, const MString& objectName,
448 MString function) {
449 maia::alloc::checkPointer(a, objectName, function);
450 maia::alloc::debug_collector(objectName, maxSize, function);
451 a = maia::alloc::make_collector<T>(maxSize, dimension, dummy, maxNoSets);
452 maia::alloc::store_collector(a, maxSize, objectName, function);
453}
454
455
464template <class T>
465void mAlloc(Collector<T>*& a, MLong maxSize, MInt dimension, MInt dummy, MInt dummy1, const MString& objectName,
466 MString function) {
467 maia::alloc::checkPointer(a, objectName, function);
468 maia::alloc::debug_collector(objectName, maxSize, function);
469 a = maia::alloc::make_collector<T>(maxSize, dimension, dummy, dummy1);
470 maia::alloc::store_collector(a, maxSize, objectName, function);
471}
472
473
482template <class T>
483void mAlloc(Collector<T>*& a, MLong maxSize, MInt dimension, MInt distributions, MInt distributions1,
484 MInt maxNoSurfaces, MInt dummy1, const MString& objectName, MString function) {
485 maia::alloc::checkPointer(a, objectName, function);
486 maia::alloc::debug_collector(objectName, maxSize, function);
487 a = maia::alloc::make_collector<T>(maxSize, dimension, distributions, distributions1, maxNoSurfaces, dummy1);
488 maia::alloc::store_collector(a, maxSize, objectName, function);
489}
490
491
500template <class T>
501void mAlloc(Collector<T>*& a, MLong maxSize, MInt dimension, MInt distributions, const MString& objectName,
502 MString function) {
503 maia::alloc::checkPointer(a, objectName, function);
504 maia::alloc::debug_collector(objectName, maxSize, function);
505 a = maia::alloc::make_collector<T>(maxSize, dimension, distributions);
506 maia::alloc::store_collector(a, maxSize, objectName, function);
507}
508
509
515template <class T>
516void mAlloc(Collector<T>*& a, MLong maxSize, MInt dimension, const MString& objectName, MString function) {
517 maia::alloc::checkPointer(a, objectName, function);
518 maia::alloc::debug_collector(objectName, maxSize, function);
519 a = maia::alloc::make_collector<T>(maxSize, dimension);
520 maia::alloc::store_collector(a, maxSize, objectName, function);
521}
522
523
529template <class T>
530void mAlloc(Collector<T>*& a, MLong maxSize, const MString& objectName, MString function) {
531 maia::alloc::checkPointer(a, objectName, function);
532 maia::alloc::debug_collector(objectName, maxSize, function);
533 a = maia::alloc::make_collector<T>(maxSize);
534 maia::alloc::store_collector(a, maxSize, objectName, function);
535}
536
537
543template <class T>
545 using namespace maia::alloc;
546 if(a == nullptr) {
547#ifdef MAIA_EXTRA_DEBUG
548 m_log << "cannot deallocate zero pointer " << a << std::endl;
549#endif
550 return false;
551 }
552
553 std::vector<GenericObject*>::iterator hit;
554 const MInt count = findAllocatedObject(a, hit);
555
556#ifdef MAIA_EXTRA_DEBUG
557 if(count > 0)
558 m_log << "Deallocating " << (*hit)->getName() << "."
559 << " " << &a << " " << count << std::endl;
560 m_log.flush();
561 if(count > 0)
562 std::cerr << "Deallocating " << (*hit)->getName() << "."
563 << " " << &a << " " << count << std::endl;
564#endif
565
566 if(count <= 0) {
567#ifndef NDEBUG
568 std::cerr << "mDeallocate error: " << count << " " << a << std::endl;
569 if(count == 0) {
570 std::cerr << "Pointer should have been reset to nullptr!" << std::endl;
571 }
572#endif
573 a = nullptr;
574 return false;
575 }
576
577
578 for(MInt k = count; k--;) {
579 delete *(hit + k);
580 }
581
582 if(count == 1)
583 g_allocatedObjects.erase(hit);
584 else if(count > 1)
585 g_allocatedObjects.erase(hit, hit + count);
586
587 if(count > 0) {
588 a = nullptr;
589 }
590
591 return (count > 0);
592}
593
599void mDealloc();
600
607 for(auto&& obj : maia::alloc::g_allocatedObjects) {
608#ifdef MAIA_EXTRA_DEBUG
609 std::cout << "Name " << obj->getName() << " Function " << obj->getCallingFunction() << std::endl;
610#else
611 std::cout << "Name " << obj->getName() << std::endl;
612#endif
613 }
614 std::cout << "Total number of allocated objects: " << maia::alloc::g_allocatedObjects.size() << std::endl;
615}
616
622#ifdef MAIA_EXTRA_DEBUG
623inline void printAllocatedObjects(const MString& filterString) {
624 for(auto&& obj : maia::alloc::g_allocatedObjects) {
625 const MString fName = obj->getCallingFunction();
626 const MBool containsFilterString = (fName.find(filterString) != std::string::npos);
627 if(containsFilterString) {
628 std::cout << filterString << ": Memory for " << obj->getName() << " from function " << fName
629 << " should have been deallocated by now!" << std::endl;
630 }
631 }
632}
633#else
634inline void printAllocatedObjects(const MString& /*filterString*/) {}
635#endif
636
637#endif
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
void printAllocatedObjects()
Prints the name of all objects which are currently allocated via mAlloc.
Definition: alloc.h:606
MLong maxAllocatedBytes()
Return the maximum number of allocated bytes.
Definition: alloc.cpp:123
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
void mDealloc()
Deallocates all memory allocated previously by mAlloc(...)
Definition: alloc.cpp:20
MLong allocatedBytes()
Return the number of allocated bytes.
Definition: alloc.cpp:121
class containing a generic pointer
Definition: genericobject.h:60
Definition: list.h:16
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
std::vector< GenericObject * > g_allocatedObjects
MBool isAllocated(const T *const a)
Check if the given pointer belongs to an allocated object.
Definition: alloc.h:90
void debug_collector(const MString &objectName, const MInt maxSize, const MString &function)
Definition: alloc.h:42
Collector< T > * make_collector(const MLong size, const MInt dummy1, const MInt dummy2, const MInt dummy3, const MInt dummy4)
Definition: alloc.h:127
void debug_list(const MString &objectName, const MInt maxSize, const MString &function)
Definition: alloc.h:48
void store_collector(Collector< T > *a, MLong maxSize, const MString &objectName, const MString &functionName)
Definition: alloc.h:116
MInt findAllocatedObject(const T *const a, std::vector< GenericObject * >::iterator &hit)
Find the allocated object for a given pointer.
Definition: alloc.h:63
void debug(const MString &objectName, const MString &elementsName)
Debug output for mAlloc.
Definition: alloc.h:31
void checkPointer(const T *const a, const MString objectName, const MString function)
Definition: alloc.h:99
Namespace for auxiliary functions/classes.
Definition: contexttypes.h:19