210 lines
7.8 KiB
C
210 lines
7.8 KiB
C
|
// File: crn_mem.h
|
||
|
// See Copyright Notice and license at the end of inc/crnlib.h
|
||
|
#pragma once
|
||
|
|
||
|
#ifndef CRNLIB_MIN_ALLOC_ALIGNMENT
|
||
|
#define CRNLIB_MIN_ALLOC_ALIGNMENT sizeof(size_t) * 2
|
||
|
#endif
|
||
|
|
||
|
namespace crnlib
|
||
|
{
|
||
|
#if CRNLIB_64BIT_POINTERS
|
||
|
const uint64 CRNLIB_MAX_POSSIBLE_BLOCK_SIZE = 0x400000000ULL;
|
||
|
#else
|
||
|
const uint32 CRNLIB_MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;
|
||
|
#endif
|
||
|
|
||
|
void* crnlib_malloc(size_t size);
|
||
|
void* crnlib_malloc(size_t size, size_t* pActual_size);
|
||
|
void* crnlib_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true);
|
||
|
void* crnlib_calloc(size_t count, size_t size, size_t* pActual_size = NULL);
|
||
|
void crnlib_free(void* p);
|
||
|
size_t crnlib_msize(void* p);
|
||
|
void crnlib_print_mem_stats();
|
||
|
void crnlib_mem_error(const char* p_msg);
|
||
|
|
||
|
// omfg - there must be a better way
|
||
|
|
||
|
template<typename T>
|
||
|
inline T* crnlib_new()
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
if (CRNLIB_IS_SCALAR_TYPE(T))
|
||
|
return p;
|
||
|
return helpers::construct(p);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A>
|
||
|
inline T* crnlib_new(const A& init0)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A>
|
||
|
inline T* crnlib_new(A& init0)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9, const K& init10)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9, init10);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L>
|
||
|
inline T* crnlib_new(const A& init0, const B& init1, const C& init2, const D& init3, const E& init4, const F& init5, const G& init6, const H& init7, const I& init8, const J& init9, const K& init10, const L& init11)
|
||
|
{
|
||
|
T* p = static_cast<T*>(crnlib_malloc(sizeof(T)));
|
||
|
return new (static_cast<void*>(p)) T(init0, init1, init2, init3, init4, init5, init6, init7, init8, init9, init10, init11);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline T* crnlib_new_array(uint32 num)
|
||
|
{
|
||
|
if (!num) num = 1;
|
||
|
|
||
|
uint64 total = CRNLIB_MIN_ALLOC_ALIGNMENT + sizeof(T) * num;
|
||
|
if (total > CRNLIB_MAX_POSSIBLE_BLOCK_SIZE)
|
||
|
{
|
||
|
crnlib_mem_error("crnlib_new_array: Array too large!");
|
||
|
return NULL;
|
||
|
}
|
||
|
uint8* q = static_cast<uint8*>(crnlib_malloc(static_cast<size_t>(total)));
|
||
|
|
||
|
T* p = reinterpret_cast<T*>(q + CRNLIB_MIN_ALLOC_ALIGNMENT);
|
||
|
|
||
|
reinterpret_cast<uint32*>(p)[-1] = num;
|
||
|
reinterpret_cast<uint32*>(p)[-2] = ~num;
|
||
|
|
||
|
if (!CRNLIB_IS_SCALAR_TYPE(T))
|
||
|
{
|
||
|
helpers::construct_array(p, num);
|
||
|
}
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline void crnlib_delete(T* p)
|
||
|
{
|
||
|
if (p)
|
||
|
{
|
||
|
if (!CRNLIB_IS_SCALAR_TYPE(T))
|
||
|
{
|
||
|
helpers::destruct(p);
|
||
|
}
|
||
|
crnlib_free(p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline void crnlib_delete_array(T* p)
|
||
|
{
|
||
|
if (p)
|
||
|
{
|
||
|
const uint32 num = reinterpret_cast<uint32*>(p)[-1];
|
||
|
const uint32 num_check = reinterpret_cast<uint32*>(p)[-2];
|
||
|
CRNLIB_ASSERT(num && (num == ~num_check));
|
||
|
if (num == ~num_check)
|
||
|
{
|
||
|
if (!CRNLIB_IS_SCALAR_TYPE(T))
|
||
|
{
|
||
|
helpers::destruct_array(p, num);
|
||
|
}
|
||
|
|
||
|
crnlib_free(reinterpret_cast<uint8*>(p) - CRNLIB_MIN_ALLOC_ALIGNMENT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace crnlib
|
||
|
#define CRNLIB_DEFINE_NEW_DELETE \
|
||
|
void* operator new (size_t size) \
|
||
|
{ \
|
||
|
void* p = crnlib::crnlib_malloc(size); \
|
||
|
if (!p) \
|
||
|
crnlib_fail("new: Out of memory!", __FILE__, __LINE__); \
|
||
|
return p; \
|
||
|
} \
|
||
|
void* operator new[] (size_t size) \
|
||
|
{ \
|
||
|
void* p = crnlib::crnlib_malloc(size); \
|
||
|
if (!p) \
|
||
|
crnlib_fail("new[]: Out of memory!", __FILE__, __LINE__); \
|
||
|
return p; \
|
||
|
} \
|
||
|
void operator delete (void* p_block) \
|
||
|
{ \
|
||
|
crnlib::crnlib_free(p_block); \
|
||
|
} \
|
||
|
void operator delete[] (void* p_block) \
|
||
|
{ \
|
||
|
crnlib::crnlib_free(p_block); \
|
||
|
}
|