/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/sgx/core/memory/allocbase.hpp

*/

#ifndef SGX_CORE_MEMORY_ALLOCBASE_HPP
#define SGX_CORE_MEMORY_ALLOCBASE_HPP	1

#include "sgx/core/helpers/trace.hpp"

/*
Each memory block is essentially:
 
+--------------+---+---------+---+------------+
|              | p |         | p |            |
| Housekeeping | a | Backptr | a | Users data |
|              | d |         | d |            |
+--------------+---+---------+---+------------+
*/
#define SGX_NEW(_t)						new (CSGXMemoryAllocator::alloc(sizeof(_t), CSGXMemoryAllocator::m_DefaultAlignment, __FILE__, __LINE__)) _t
#define SGX_DELETE(_v,_t)				_v->~_t(), CSGXMemoryAllocator::free(_v)

#define sgxAlloc(sz)					CSGXMemoryAllocator::alloc(sz, CSGXMemoryAllocator::m_DefaultAlignment, __FILE__, __LINE__)
#define sgxCalloc(typesz,typecount)		CSGXMemoryAllocator::calloc(typesz, typecount, CSGXMemoryAllocator::m_DefaultAlignment, __FILE__, __LINE__)
#define sgxRealloc(prev,sz)				CSGXMemoryAllocator::realloc(prev, sz, CSGXMemoryAllocator::m_DefaultAlignment, __FILE__, __LINE__)
#define sgxFree(ptr)					CSGXMemoryAllocator::free(ptr)

class CSGXMemoryAllocator;

class CSGXMemoryHouseKeeping {
public:
	CSGXMemoryAllocator *	m_pAllocator;
	tMEM_SIZE 				m_Size;
#if SGX_DEBUG
	tCHAR					m_Filename[256];
	tUINT32					m_LineNumber;
#endif	
};
 
class CSGXMemoryInformationBlock { 
public:
	CSGXMemoryHouseKeeping *	m_pBackPtr;
};
 
class CSGXMemoryAlignment {
public:
	tMEM_SIZE	m_StartAlignment;
	tMEM_SIZE	m_SizeAlignment;
	tMEM_SIZE	m_MinimumSize;
 
	CSGXMemoryAlignment() {
		m_StartAlignment = 1;
		m_SizeAlignment = 1;
		m_MinimumSize = 0;
	}
 
	CSGXMemoryAlignment(tMEM_SIZE startAlign, tMEM_SIZE sizeAlign, tMEM_SIZE minimumSize) {
		m_StartAlignment = startAlign;
		m_SizeAlignment = sizeAlign;
		m_MinimumSize = minimumSize;
	}
 
};

 
class CSGXMemoryAllocator {
public:
	CSGXMemoryAllocator(void *ptr, const tMEM_SIZE size, const CSGXMemoryAlignment &alignment);
 
	virtual void *alloc(const tMEM_SIZE size)=0;
	virtual tMEM_SIZE getBlockSize(void *ptr) { SGX_UNUSED(ptr); return 0; }
	virtual tBOOL freeAll();
 
 
	// For debugging
	virtual tBOOL reportAll();
 
	//
	static CSGXMemoryAllocator *setDefault(CSGXMemoryAllocator *pNewDefault);
 
	// use the default allocator
	//static void *alloc(const tMEM_SIZE size);
	static void *alloc(const tMEM_SIZE size, const CSGXMemoryAlignment &alignment, const char *pFilename=NULL, const int lineNumber=0);
	static void *calloc(const tMEM_SIZE typeSize, const tMEM_SIZE typeCount, const CSGXMemoryAlignment &alignment, const char *pFilename=NULL, const int lineNumber=0);
	static void *realloc(void *prev, const tMEM_SIZE size, const CSGXMemoryAlignment &alignment, const char *pFilename=NULL, const int lineNumber=0);
	static tMEM_SIZE getSize(void *ptr);
	static tBOOL free(void *ptr);
	//
	static CSGXMemoryAlignment	m_DefaultAlignment;
 
protected:
	CSGXMemoryAllocator() {  }
	tBYTE *				m_pBlock;
	tMEM_SIZE 			m_iBlockSize;
	CSGXMemoryAlignment m_Alignment;
	
     virtual tBOOL freePtr(void *ptr);

private:
	static CSGXMemoryHouseKeeping *getHousekeepingBlock(void *ptr);
	static CSGXMemoryAllocator *getAllocator(void *ptr);
 
	static CSGXMemoryAllocator	*m_pDefaultAllocator;
};
 
#endif
 