mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 22:00:33 +05:00
319 lines
6.6 KiB
C++
319 lines
6.6 KiB
C++
|
#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);
|
||
|
}
|
||
|
|
||
|
virtual void Delete(void* p) {}
|
||
|
|
||
|
virtual void ArrayDelete(void* p) {}
|
||
|
private:
|
||
|
///
|
||
|
#ifndef __CUDA_ARCH__
|
||
|
[[noreturn]] NGCORE_API void ThrowException();
|
||
|
#else
|
||
|
NETGEN_INLINE void ThrowException() { ; }
|
||
|
#endif
|
||
|
|
||
|
public:
|
||
|
/// free memory (dummy function)
|
||
|
NETGEN_INLINE void Free (void * data) throw ()
|
||
|
{
|
||
|
;
|
||
|
}
|
||
|
|
||
|
/// 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
|