#ifndef _xbHEAPLOW_
#define _xbHEAPLOW_
/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: xbHeapLow
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<10/02/2014: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#ifndef _xbHEAPBASE_
#	include "xbHeapBase.h"
#endif

#ifdef _xbALLOCDEBUG
#	define	xbSTATICHEAP_HDRLEN	(sizeof(_CellHeader)+sizeof(_xbDebugAllocSt)+_xbDEBUGHEAP_HDRLEN)
#else
#	define	xbSTATICHEAP_HDRLEN	(sizeof(_CellHeader)+_xbDEBUGHEAP_HDRLEN)
#endif
#define	xbSTATICHEAP_ENDLEN	(_xbDEBUGHEAP_ENDLEN)
#define	xbSTATICHEAP_MINLEN	(xbSTATICHEAP_HDRLEN+32+_xbDEBUGHEAP_ENDLEN)
#define xbSTATICHEAP_MINCELL 16

class xbEXPORT xbStaticHeapBase:public xbBaseHeap
{
public:
	xbStaticHeapBase(const char *pszDbgName, size_t cByteSeg, size_t cByteCell, byte *pSeg, xbCtorMode CtorMode = xbCtor_CallCreate);
	xbStaticHeapBase(const char *pszDbgName);
	virtual ~xbStaticHeapBase();

	void	SetParams(size_t cByteSeg, size_t cByteCell, byte *pSeg);
	void	GetParams(size_t *pcByteSeg, size_t *pcByteCell, byte **ppSeg, bool bReal = true) const;
	void	Create();
	void	Destroy();

	//sIxbHeap methods
	/*virtual*/ void	*Alloc(size_t cByte,xbAllocMode AllocMode
#ifdef _xbALLOCDEBUG
		,const char *pszFile,int nLine
#endif
		);
	/*virtual*/ void	*ReAlloc(void *ptr,size_t cByte,xbAllocMode AllocMode
#ifdef _xbALLOCDEBUG
		,const char *pszFile,int nLine
#endif
		);
	/*virtual*/ void	Free(void *ptr);

	/*virtual*/ char *AllocString(const char *pszStr
#ifdef _xbALLOCDEBUG
		,const char *pszFile,int nLine
#endif
		);

	virtual void	Clear();
	virtual xbint	GetSize(void *ptr) const;
	virtual int64	GetSize() const
	{
		return xbBaseHeap::GetSize();
	}
	virtual bool	IsValid() const;
	virtual bool	IsValid(void *ptr) const;
	virtual bool	Compact();
	virtual void	DebugDump() const;
	virtual int64	GetBusySize() const;

	bool IsCreated() const {return m_bCreated;}
	size_t SizeAlign(size_t cByte)
	{
		return (cByte+xbSTATICHEAP_HDRLEN+xbSTATICHEAP_ENDLEN+m_cByteCell-1) / m_cByteCell * m_cByteCell;
	}
protected:
	virtual void throwEnotCreated();
	virtual void throwEmem(ulong cByteBlock);

	mutable xbSectShareSimpleRec	m_Share;

	bool					m_bCreated;

	//Params set by SetParams().
	size_t				m_cByteCell;
	size_t				m_cByteSeg;
	byte				*m_pSeg;

	//Execution status params
	size_t				m_cByteBusy;

	bool					_isValid(void *pBloc) const;

#if defined(xbHEAPRELEASECHECK) || defined(_DEBUG)
	void					_checkBlock(void *pBloc) const;
#endif
#define xbSTATICHEAP_FREECELL 0x80000000
	struct _CellHeader
	{
		ulong	m_cByte;
	};

	_CellHeader				*_freeBlockFind(ulong cByte);
private:
	xbDclNoNewForObject(xbStaticHeapBase);
	xbDclNoCopyForObject(xbStaticHeapBase);
};

template<size_t t_cByteSeg,size_t t_cByteCell = 64> class xbStaticHeap:public xbStaticHeapBase
{
public:
	xbStaticHeap(const char *pszDbgName)
		:xbStaticHeapBase(pszDbgName,sizeof(m_seg),t_cByteCell,m_seg)
	{
	}

	virtual void	SetParams(size_t cByteSeg, size_t cByteCell, byte *pSeg)
	{
		xbThrowEsys("xbStaticHeap::SetParams not available");
	}
	virtual void	GetParams(size_t *pcByteSeg,size_t *pcByteCell, byte **ppSeg, bool bReal = true) const
	{
		xbStaticHeapBase::GetParams(pcByteSeg,pcByteCell,ppSeg,bReal);
		if (!bReal)
		{
			if (pcByteSeg)
				*pcByteSeg = t_cByteSeg;
			if (pcByteCell)
				*pcByteCell = t_cByteCell;
		}			
	}

protected:
	byte	m_seg[_xbHEAPALIGN(t_cByteCell+xbSTATICHEAP_HDRLEN+xbSTATICHEAP_ENDLEN) * (t_cByteSeg/t_cByteCell)];
private:
	xbDclNoNewForObject(xbStaticHeap);
	xbDclNoCopyForObject(xbStaticHeap);
};

class xbEXPORT xbLowExceptionHeap:public xbStaticHeap<1024*128>
{
public:
	xbLowExceptionHeap(const char *pszDbgName)
		:xbStaticHeap(pszDbgName)
	{
	}
protected:
	virtual void throwEnotCreated() {}
	virtual void throwEmem(ulong cByteBlock) {}
private:
	xbDclNoNewForObject(xbLowExceptionHeap);
	xbDclNoCopyForObject(xbLowExceptionHeap);
};

extern xbEXPORT xbLowExceptionHeap g_xbLowExceptionHeap;

#define xbLowExceptionHeapDnewImpl(clsname) \
		xbHeapDnewImpl(clsname,g_xbLowExceptionHeap)

#endif
