202 lines
7.4 KiB
C++
202 lines
7.4 KiB
C++
/** @file
|
|
* @author Edouard DUPIN
|
|
* @copyright 2017, Edouard DUPIN, all right reserved
|
|
* @license MPL v2.0 (see license file)
|
|
*/
|
|
#pragma once
|
|
#include <etk/types.hpp>
|
|
|
|
// it is define bu generic "include <new>" ==> no double define of placement new
|
|
#ifndef _NEW
|
|
// Default placement versions of operator new (use char* instead of void* to permit no multiple definition).
|
|
inline void* operator new(size_t, char* _p) throw() {
|
|
return _p;
|
|
}
|
|
inline void operator delete (void*, char*) throw() {
|
|
|
|
}
|
|
#endif
|
|
|
|
//#define ETK_MEMORY_CHECKER 2
|
|
|
|
#ifndef ETK_MEMORY_CHECKER
|
|
#define ETK_MEMORY_CHECKER 0
|
|
#endif
|
|
|
|
#if ETK_MEMORY_CHECKER > 0
|
|
namespace etk {
|
|
namespace memory {
|
|
/**
|
|
* @brief Create an allocation memory and set start and stop header. Log in the curent structure.
|
|
* If no more free element in the basic structure, the system allocate without saving information and header start and stop
|
|
* @param[in] _num number of alament needed to allocate
|
|
* @param[in] _size Size of one element to allocate
|
|
* @param[in] _variableName Variable name to allocate (must be a real static cont never removed)
|
|
* @param[in] _functionName Fonction Name where allocation is done (must be a real static cont never removed)
|
|
* @param[in] _line Line where allocation is done.
|
|
* @param[in] _fileName File where allocation is done. (must be a real static cont never removed)
|
|
* @return pointer on the current memory allocation. (or NULL if an error occured)
|
|
*/
|
|
void* allocate(size_t _num, size_t _size, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName);
|
|
/**
|
|
* @brief Free Memory with the dedicate pointer
|
|
* If the memory is not saved the current pointer is free, else we get the real pointer and free it
|
|
* @param[in,out] _pointerData User pointer Data.
|
|
* @param[in] _variableName Variable name where free is done. (must be a real static cont never removed)
|
|
* @param[in] _functionName Fonction name where free is done. (must be a real static cont never removed)
|
|
* @param[in] _line line where free is done.
|
|
* @param[in] _fileName file where free is done. (must be a real static cont never removed)
|
|
*/
|
|
void remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName);
|
|
/**
|
|
* @brief Display all memory not free by this system.
|
|
* @param[in] _statusOnly Display only the memory allocation status.
|
|
*/
|
|
void display(bool _statusOnly=true);
|
|
/**
|
|
* @brief Check if memory have not write out of the range.
|
|
*/
|
|
bool check();
|
|
/**
|
|
* @brief Check if the pointer is already register in the allocator (can not predist the size, but permti to know where the error came from in debug mode
|
|
* @param[in] _pointerPointer on the data to check
|
|
* @return true the pointer is set
|
|
* @return false the pointer is not set
|
|
*/
|
|
bool checkPointer(void* _pointer);
|
|
/**
|
|
* @brief Create a snapshoot of the memory
|
|
* @return handle on the snapshoot
|
|
*/
|
|
uint64_t* createSnapshoot();
|
|
/**
|
|
* @brief Check if a snapshoot is correct (no change)
|
|
* @param[in] _handle Handle on the snapshoot
|
|
* @return true the memory is identical
|
|
*/
|
|
bool checkSnapshoot(uint64_t* _handle);
|
|
/**
|
|
* @brief Free the snapshoot handle
|
|
* @param[in] _handle Handle on the snapshoot
|
|
*/
|
|
void clearSnapshoot(uint64_t* _handle);
|
|
/**
|
|
* @brief When reallocate data and permit to the allocator to not warning when check the the snapshoot
|
|
*/
|
|
void flipID(void* _pointer1, void* _pointer2);
|
|
|
|
template<class ETK_TYPE,
|
|
class... ETK_MEMORY_ARGS>
|
|
ETK_TYPE* allocatorNew(ETK_MEMORY_ARGS&& ... _args) {
|
|
char* tmp = (char*)etk::memory::allocate(1, sizeof(ETK_TYPE), "new", __func__, __LINE__, __FILE__);
|
|
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
|
}
|
|
template<class ETK_TYPE,
|
|
class... ETK_MEMORY_ARGS>
|
|
ETK_TYPE* allocatorNewSize(size_t _size, ETK_MEMORY_ARGS&& ... _args) {
|
|
char* tmp = (char*)etk::memory::allocate(_size, sizeof(ETK_TYPE), "new", __func__, __LINE__, __FILE__);
|
|
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
|
}
|
|
template<class ETK_TYPE,
|
|
class... ETK_MEMORY_ARGS>
|
|
ETK_TYPE* allocatorNewFull(const char* _variableName,
|
|
const char* _functionName,
|
|
int32_t _line,
|
|
const char* _fileName,
|
|
ETK_MEMORY_ARGS&& ... _args) {
|
|
char* tmp = (char*)etk::memory::allocate(1, sizeof(ETK_TYPE), _variableName, _functionName, _line, _fileName);
|
|
return new (tmp) ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
|
}
|
|
template<class ETK_TYPE>
|
|
void allocatorDelete(ETK_TYPE* _element,
|
|
const char* _variableName = "",
|
|
const char* _functionName = "",
|
|
int32_t _line = __LINE__,
|
|
const char* _fileName = __FILE__) {
|
|
if (_element == null) {
|
|
return;
|
|
}
|
|
_element->~ETK_TYPE();
|
|
etk::memory::remove((void*)_element, _variableName, _functionName, _line, _fileName);
|
|
_element = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define ETK_NEW(type, ...) \
|
|
new ((char*)etk::memory::allocate(1, sizeof(type), #type, __func__, __LINE__, __FILE__)) type(__VA_ARGS__)
|
|
|
|
#define ETK_DELETE(type, pointerData) \
|
|
etk::memory::allocatorDelete((type*)(pointerData), #type, __func__, __LINE__, __FILE__)
|
|
|
|
#define ETK_MALLOC(type, nbElements) \
|
|
((type *)etk::memory::allocate( (nbElements), sizeof(type), #type, __func__, __LINE__, __FILE__))
|
|
|
|
#define ETK_FREE(type, pointerData) \
|
|
etk::memory::remove( (pointerData), #type, __func__, __LINE__, __FILE__)
|
|
|
|
#define ETK_MEM_SHOW_LOG(...) \
|
|
etk::memory::display(__VA_ARGS__)
|
|
|
|
#define ETK_MEM_CHECK() \
|
|
etk::memory::check()
|
|
|
|
#define ETK_MEM_CHECK_POINTER(pointer) \
|
|
etk::memory::checkPointer(pointer)
|
|
|
|
#define ETK_MEM_FLIP_ID(pointer1, pointer2) \
|
|
etk::memory::flipID((void*)pointer1, (void*)pointer2)
|
|
#else
|
|
namespace etk {
|
|
namespace memory {
|
|
template<class ETK_TYPE,
|
|
class... ETK_MEMORY_ARGS>
|
|
ETK_TYPE* allocatorNew(ETK_MEMORY_ARGS&& ... _args) {
|
|
return new ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
|
}
|
|
template<class ETK_TYPE,
|
|
class... ETK_MEMORY_ARGS>
|
|
ETK_TYPE* allocatorNewFull(const char* _variableName,
|
|
const char* _functionName,
|
|
int32_t _line,
|
|
const char* _fileName,
|
|
ETK_MEMORY_ARGS&& ... _args) {
|
|
return new ETK_TYPE(etk::forward<ETK_MEMORY_ARGS>(_args)...);
|
|
}
|
|
template<class ETK_TYPE>
|
|
void allocatorDelete(ETK_TYPE* _element,
|
|
const char* _variableName = "",
|
|
const char* _functionName = "",
|
|
int32_t _line = __LINE__,
|
|
const char* _fileName = __FILE__) {
|
|
delete _element;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define ETK_NEW(type, ...) \
|
|
new type(__VA_ARGS__)
|
|
|
|
#define ETK_DELETE(type, pointerData) \
|
|
delete ((type*)(pointerData))
|
|
|
|
#define ETK_MALLOC(dataType, nbElements) \
|
|
(dataType *)new dataType[nbElements]
|
|
|
|
#define ETK_FREE(type, pointerData) \
|
|
delete[] (type*)pointerData
|
|
|
|
#define ETK_MEM_SHOW_LOG(...) \
|
|
do { } while(false)
|
|
|
|
#define ETK_MEM_CHECK() \
|
|
do {} while(false)
|
|
|
|
#define ETK_MEM_CHECK_POINTER(pointer) \
|
|
do {} while(false)
|
|
|
|
#define ETK_MEM_FLIP_ID(pointer1, pointer2) \
|
|
do {} while(false)
|
|
|
|
#endif
|