netgen/libsrc/core/localheap.hpp

319 lines
6.6 KiB
C++
Raw Normal View History

2019-07-09 21:07:19 +05:00
#ifndef NETGEN_CORE_LOCALHEAP_HPP
#define NETGEN_CORE_LOCALHEAP_HPP
/**************************************************************************/
/* File: localheap.hpp */
/* Author: Joachim Schoeberl */
/* Date: 19. Apr. 2000 */
/**************************************************************************/
#include <cstdlib>
#include "exception.hpp"
#include "ngcore_api.hpp"
#include "utils.hpp"
namespace ngcore
{
class Allocator
{
public:
virtual ~Allocator() {}
virtual void * Alloc (size_t size)
{
return new char[size];
}
virtual void Delete(void* p)
{
delete (char*) p;
}
virtual void ArrayDelete(void* p)
{
delete [] (char*) p;
}
};
static Allocator global_alloc;
/**
Exception on heap overflow.
Thrown by allocation on LocalHeap.
*/
class NGCORE_API LocalHeapOverflow : public Exception
{
public:
LocalHeapOverflow (size_t size);
virtual ~LocalHeapOverflow ();
};
/**
Optimized memory handler.
One block of data is organized as stack memory.
One can allocate memory out of it. This increases the stack pointer.
With \Ref{CleanUp}, the pointer is reset to the beginning or to a
specific position.
*/
class LocalHeap : public Allocator
{
char * data;
char * next;
char * p;
size_t totsize;
public:
bool owner;
const char * name;
#if defined(__MIC__) || defined (__AVX512F__)
enum { ALIGN = 64 };
#else
enum { ALIGN = 32 };
#endif
public:
/// Allocate one block of size asize.
NGCORE_API LocalHeap (size_t asize,
const char * aname = "noname",
bool mult_by_threads = false);
/// Use provided memory for the LocalHeap
NETGEN_INLINE LocalHeap (char * adata, size_t asize,
const char * aname = "noname") throw ()
{
totsize = asize;
data = adata;
next = data + totsize;
owner = 0;
// p = data;
name = aname;
CleanUp();
}
/*
/// Use provided memory for the LocalHeap
NETGEN_INLINE LocalHeap (const LocalHeap & lh2)
: data(lh2.data), p(lh2.p), totsize(lh2.totsize), owner(false),
name(lh2.name)
{
next = data + totsize;
}
*/
NETGEN_INLINE LocalHeap (const LocalHeap & lh2) = delete;
NETGEN_INLINE LocalHeap (LocalHeap && lh2)
: data(lh2.data), p(lh2.p), totsize(lh2.totsize), owner(lh2.owner),
name(lh2.name)
{
next = data + totsize;
lh2.owner = false;
}
NETGEN_INLINE LocalHeap Borrow()
{
return LocalHeap (p, Available());
}
NETGEN_INLINE LocalHeap & operator= (LocalHeap && lh2)
{
if (owner)
delete [] data;
data = lh2.data;
p = lh2.p;
totsize = lh2.totsize;
owner = lh2.owner;
name = lh2.name;
next = data + totsize;
lh2.owner = false;
return *this;
}
NETGEN_INLINE LocalHeap ()
: data(nullptr), next(nullptr), p(nullptr), totsize(0), owner(false) { ; }
/// free memory
NETGEN_INLINE virtual ~LocalHeap ()
{
if (owner)
delete [] data;
}
/// delete all memory on local heap
NETGEN_INLINE void CleanUp() throw ()
{
p = data;
// p += (16 - (long(p) & 15) );
p += (ALIGN - (size_t(p) & (ALIGN-1) ) );
}
/// returns heap-pointer
NETGEN_INLINE void * GetPointer () throw ()
{
return p;
}
/// deletes memory back to heap-pointer
NETGEN_INLINE void CleanUp (void * addr) throw ()
{
p = (char*)addr;
}
/// allocates size bytes of memory from local heap
NETGEN_INLINE void * Alloc (size_t size) final // throw (LocalHeapOverflow)
{
char * oldp = p;
// 16 byte alignment
size += (ALIGN - size % ALIGN);
p += size;
// if ( size_t(p - data) >= totsize )
#ifndef FULLSPEED
if (likely(p >= next))
ThrowException();
#endif
return oldp;
}
/// allocates size objects of type T on local heap
template <typename T>
NETGEN_INLINE T * Alloc (size_t size) // throw (LocalHeapOverflow)
{
char * oldp = p;
size *= sizeof (T);
// 16 byte alignment
size += (ALIGN - size % ALIGN);
p += size;
#ifndef FULLSPEED
if (likely(p >= next))
ThrowException();
#endif
return reinterpret_cast<T*> (oldp);
}
2021-02-18 14:30:01 +05:00
virtual void Delete(void* /* p */) {}
2019-07-09 21:07:19 +05:00
2021-02-18 14:30:01 +05:00
virtual void ArrayDelete(void* /* p */) {}
2019-07-09 21:07:19 +05:00
private:
///
#ifndef __CUDA_ARCH__
[[noreturn]] NGCORE_API void ThrowException();
#else
NETGEN_INLINE void ThrowException() { ; }
#endif
public:
/// free memory (dummy function)
2021-02-18 14:30:01 +05:00
NETGEN_INLINE void Free (void * /* data */) throw ()
2019-07-09 21:07:19 +05:00
{
;
}
/// available memory on LocalHeap
NETGEN_INLINE size_t Available () const throw () { return (totsize - (p-data)); }
/// Split free memory on heap into pieces for each thread
NGCORE_API LocalHeap Split () const;
/// Split free memory on heap into pieces
NETGEN_INLINE LocalHeap Split (int partnr, int nparts) const
{
int pieces = nparts;
int i = partnr;
size_t freemem = totsize - (p - data);
size_t size_of_piece = freemem / pieces;
return LocalHeap (p + i * size_of_piece, size_of_piece, name);
}
NETGEN_INLINE void ClearValues ()
{
for (size_t i = 0; i < totsize; i++) data[i] = 47;
}
NETGEN_INLINE size_t UsedSize ()
{
for (size_t i = totsize-1; i != 0; i--)
if (data[i] != 47) return i;
return 0;
}
};
/**
Optimized memory handler.
Provides static memory for the local heap. The template argument specifies the size in number of chars.
*/
template <int S>
class LocalHeapMem : public LocalHeap
{
char mem[S];
public:
NETGEN_INLINE LocalHeapMem (const char * aname) throw () : LocalHeap (mem, S, aname) { ; }
};
/**
A reset for the heap-pointer of a LocalHeap..
The constructor stores the heap-pointer, the constructor at the end of the regions resets the heap-pointer.
*/
class HeapReset
{
LocalHeap & lh;
void * pointer;
public:
///
NETGEN_INLINE HeapReset (LocalHeap & alh)
: lh(alh), pointer (alh.GetPointer()) { ; }
///
NETGEN_INLINE ~HeapReset ()
{
lh.CleanUp (pointer);
}
};
}
NETGEN_INLINE void * operator new (size_t size, ngcore::Allocator & alloc)
{
return alloc.Alloc(size);
}
NETGEN_INLINE void * operator new [] (size_t size, ngcore::Allocator & alloc)
{
return alloc.Alloc(size);
}
NETGEN_INLINE void operator delete (void * p, ngcore::Allocator & lh)
{
lh.Delete(p);
}
NETGEN_INLINE void operator delete [] (void * p, ngcore::Allocator & lh)
{
lh.ArrayDelete(p);
}
#endif // NETGEN_CORE_LOCALHEAP_HPP