/*******************************************************************************
*	ファイル名：Mem.h
*	用　　　途：メモリバッファ管理クラス定義
*	備　　　考：
*	履　　　歴：
********************************************************************************/

/****************************
*	 コンパイル環境設定		*
****************************/
#pragma once

/****************************
*	インクルードファイル	*
****************************/
#include <AfxTempl.h>

/****************************
*	　マクロ・定数定義		*
****************************/
#ifndef divc
#define divc( n, d )	( ((n)+(d)-1) / (d) )
#endif

#ifndef IALIGN
#define IALIGN( n, d )	( divc(n, d) * (d) )
#endif

/// バイト単位系定数
#define _KB							(1024)
#define _MB							( _KB * _KB )
#define _GB							( _MB * _KB )
#define _64KB						(64*1024)
#define _4MB						(4*1024*1024)
#define SECTOR_ALLOC_MULTIPLY		64
#define MEM_ALIGNED					MEMORY_ALLOCATION_ALIGNMENT

/****************************
*		 構造体定義			*
****************************/
/// メモリ区画(セクター)構造体
struct MEM_SECTOR
{
	SIZE_T			uiAllocBytes ;			// 確保済みバイトサイズ
	INT32			nAllocCount ;			// 確保バッファ数
	BYTE*			pMem ;					// セクター先頭ポインタ
} ;

/****************************
*		 クラス定義			*
****************************/

/*******************************************************************************
*	ク ラ ス名：CMemBuffer
*	用　　　途：メモリバッファークラス
*	備　　　考：nブロックのバッファクラス
********************************************************************************/
class CMemBuffer
{
public:
	/// 生成と消滅
								CMemBuffer() ;
							   ~CMemBuffer() ;

public:
	/// 公開インターフェース
				BOOL			Alloc( SIZE_T	uiBlockBytes	
									 , INT32	nBlockCount = 1
									 , BOOL		bInit = TRUE 
									 ) ;						// メモリ割り当て
				BOOL			Free() ;						// メモリの解放
				BOOL			Setup( SIZE_T	uiBlockBytes
									 , INT32	nBlockCount = 1
									 , BOOL		bInit =TRUE
									 ) ;						// メモリのセットアップ
				BYTE*			GetPtr( INT32 nBlockNo=0 ) ;	// ブロックメモリ取得
				BYTE*			operator[]( INT32 nBlockNo ) ;	// インデックスオペレータ
				SIZE_T			BlockBytes() const ;			// ブロックサイズ取得
				SIZE_T			AlignBytes() const ;			// アライメント済みブロックサイズ取得
				INT32			BlockCount() const ;			// 総ブロック数取得
				BOOL			IsValidBlock
									( BYTE* pbyBlock ) const ;	// 対象ブロックが有効範囲にあるかチェックする
				BOOL			Clear( INT32 nBlockNo=-1 ) ;	// 対象ブロックのクリア

private:
	/// 内部メソッド
				void			InitMember() ;					// メンバー変数の初期化
				BOOL			DoAlloc( SIZE_T	uiBlockBytes
									   , INT32	nBlockCount
									   , BOOL	bInit 
									   ) ;						// メモリ割り当て
				BOOL			DoFree() ;						// メモリ解放
				SIZE_T			DoCalcMaxSectorBytes
									( SIZE_T uiAlignedBlockBytes
									, INT32	 nBlockCount
									) ;							// セクターバイト数計算
				void			SubInitAllocUnits() ;			// 割り当て単位の初期化
				void			SubClearSectors() ;				// セクター領域の初期化

private:
	/// 内部メンバー
				SIZE_T			m_uiBlockBytes ;				// ブロックサイズ
				INT32			m_nBlockCount ;					// ブロック数
				SIZE_T			m_uiAlignBlockBytes ;			// アライメント済みブロックサイズ
				INT32			m_nSectorCount ;				// セクター数
				INT32			m_nMaxCountInSector ;			// セクター内最大ブロック数
				MEM_SECTOR*		m_paSectors ;					// セクター配列

				UINT32			m_uVMemUnitBytes ;				// 仮想メモリ割り当て単位
				UINT32			m_uStdSectorBytes ;				// 基準セクター確保単位
} ;


/*******************************************************************************
*	ク ラ ス名：CBlockedMemory
*	用　　　途：複数ブロックのメモリを管理するクラス
*	備　　　考：nブロックのメモリを管理する
********************************************************************************/
class CBlockedMemory
{
public:
	/// 生成と消滅
								CBlockedMemory() ;
							   ~CBlockedMemory() ;

public:
	/// 公開インターフェース
				BOOL			Setup( SIZE_T uiBlockSize
									 , USHORT usCount 
									 ) ;						// サイズ設定
				BOOL			Destroy( BOOL bForced=TRUE ) ;	// 全メモリ解放

				BYTE*			Alloc( BOOL bInit=TRUE ) ;		// メモリ割り当て
				BOOL			Free( void* p ) ;				// メモリ解放
				BOOL			Reset() ;						// メモリ使用リセット
				BOOL			IsUsed() ;						// メモリ使用中確認

private:
	/// 内部型
	/// メモリブロックコンテナ構造体
	struct Container
	{
				SLIST_ENTRY		tEntry ;						// シングルリストエントリー
				UINT32			aBuffer[1] ;					// データバッファ
																// 実際には以降にデータが格納される
	} ;

private:
	/// 内部メソッド
				void			InitMember() ;					// メンバー初期化
				BOOL			SubFreeAll() ;					// リストバッファの解放
				BOOL			SubAllocBlocks() ;				// メモリブロックの割り当て
				void			SubInitBlocks() ;				// ブロックの初期化

private:
	/// メンバー変数
				SIZE_T			m_uiBlockSize ;					// 割り当て単位サイズ
				USHORT			m_usCount ;						// 確保可能個数
				SLIST_HEADER*	m_pSListHeader ;				// シングルリンクリストヘッダ
				CMemBuffer		m_BlockBuffer ;					// ブロックバッファ
} ;


/*******************************************************************************
*	ク ラ ス名：CMemories
*	用　　　途：複数ブロックメモリを配列管理するクラス
*	備　　　考：nブロックメモリを管理する
********************************************************************************/
class CMemories
{
public:
	/// 生成と消滅
								CMemories() ;
							   ~CMemories() ;

public:
	/// 公開インターフェース
				BOOL			SetupMemories
									( UINT uQuantity ) ;		// メモリ配列のセットアップ
				BOOL			DestroyMemories() ;				// 全メモリ配列の解放

				CBlockedMemory*	RefAt( INT32 nIndex ) ;			// ブロックメモリオブジェクトの参照
				CBlockedMemory&	operator[]( INT32 nIndex ) ;	// インデクサオペレータ
				BOOL			ResetAll() ;					// 全メモリ使用状態リセット
				BOOL			DestroyAll( BOOL bForce=TRUE ) ;// 全メモリの解放
				UINT			Quantity() const ;				// メモリオブジェクト数の取得

private:
	/// 内部型定義
	typedef		CArray<CBlockedMemory*, CBlockedMemory*&> 
											BlockedMemories ;	// ブロックメモリ配列

private:
	/// メンバー変数
				BlockedMemories	m_aMemories ;					//
} ;


/****************************
*		関　数　定　義		*
****************************/
/// ローフラグメンテーションヒープ(メモリ断片化抑止)化
BOOL	SetLFH( HANDLE hHeap=NULL ) ;
/// 32bit境界アライメント済みヒープ領域の割り当て
void*	MemAlloc( SIZE_T uiSize ) ;
/// 32bit境界アライメント済みヒープ領域の割り当て・再確保
void*	MemPrealloc( void** ppMemory, SIZE_T uiSize, BOOL bInit=TRUE ) ;
/// MemAllocで確保された領域の解放
BOOL	MemFree( void* pMem ) ;
/// 簡易VirtualAlloc
void*	VAlloc( SIZE_T uiSizeBytes, BOOL bInit=TRUE ) ;
/// VAllocで確保された領域の解放
BOOL	VFree( void* pMem ) ;

