Files
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

243 lines
6.0 KiB
C++

/**
* @file NFMemPool.h
* @brief Packet Memory 관리객체
* @remarks
* @author 강동명(edith2580@gmail.com)
* @date 2009-05-09
*/
#pragma once
#include <Nave/NFSync.h>
#include <Nave/NFLog.h>
namespace NaveServer {
#pragma pack(push, struct_packing_before)
#pragma pack(1)
/**
* @class NFMemPool
* @brief IOCP에서 사용할 패킷 버퍼를 관리할 메모리Pool 클래스
* @remarks
*
* @par
* @author Edith
* @date 2009-08-28
*/
template <class TYPE>
class NFMemPool
{
public:
/// 할당 받을 갯수와 버퍼 사이즈 입력
NFMemPool(INT nTotalCnt, INT nAllocBufferSize=0);
/// 할당 해제 처리
~NFMemPool();
/**
* @brief 로그파일의 이름을 결정합니다.
* @param strLogTitle 로그의 이름
*/
VOID SetLogTitle(WCHAR* strLogTitle)
{
wcscpy(m_strLogTitle, strLogTitle);
}
/// 현재 할당 받은 수
INT GetCount();
/// 비어 있는 패킷 수
INT GetEmpty();
/// 버퍼에 따른 인덱스 얻기
INT GetIndex( TYPE *ptr );
/// 할당된 패킷중 빈 패킷 반환
TYPE* Alloc();
/// 할당 받은 메모리를 해제
BOOL Free( TYPE *ptr );
private:
/// INDEX Structure
struct INDEX
{
/// 다음 Index 포인터를 가진다
INDEX* pNext;
/// 현재 인덱스 번호
INT nIndex;
/// Structure constructure
INDEX(){
pNext = NULL;
nIndex = 0;
}
};
private:
/// 현재 할당 받은 수
INT m_nCount;
/// 만들어진 할당 패킷 수
INT m_nTotalCnt;
/// 한 패킷당 할당 받은 버퍼 사이즈
INT m_nAllocBufferSize;
/// 한 패킷당 전체 사이즈
INT m_nPerPacketSize;
/// 로그파일 이름
WCHAR m_strLogTitle[32];
/// 전체 할당 포인터
PVOID m_pPakets;
/// 현재 비어있는 처리 인덱스 포인터
INDEX* m_pFreeRoom;
Nave::NFSync m_Sync;
};
#pragma pack( pop, struct_packing_before )
template <class TYPE>
NFMemPool<TYPE>::NFMemPool( INT nTotalCnt, INT nAllocBufferSize )
{
assert( nTotalCnt > 0 );
m_nCount = 0;
m_pFreeRoom = NULL;
m_pPakets = NULL;
m_nTotalCnt = nTotalCnt; // MAXUSER * 2
m_nAllocBufferSize = nAllocBufferSize; // 1024 + 64
m_nPerPacketSize = sizeof(INDEX) + sizeof(TYPE) + m_nAllocBufferSize;
m_pPakets = VirtualAlloc( NULL,
m_nTotalCnt * m_nPerPacketSize,
MEM_RESERVE | MEM_COMMIT, // reserve and commit
PAGE_READWRITE );
//////////////////////////////////////////////////////////
// < 할당 데이타 블럭도 > //
// //
// ----------------------------------------------- //
// | INDEX | TYPE | m_nExBlockSize | //
// ----------------------------------------------- //
//////////////////////////////////////////////////////////
assert( m_pPakets );
INDEX* pIndex = (INDEX*) m_pPakets;
assert( pIndex );
//////////////////////////////////////////
// init linear linked list for buffer pool
// 할당 데이타 구조 맨 마지막 단위의 포인터 얻기
pIndex = (INDEX*) ((DWORD)pIndex + (m_nTotalCnt - 1) * m_nPerPacketSize);
// 할당 데이타 구조의 마지막 부터 Linked List를 구성하여 올라오기
for( INT i = m_nTotalCnt-1; i >= 0; i-- )
{
pIndex->pNext = m_pFreeRoom; // 맨 마지막의 pNext = NULL이다
pIndex->nIndex = i; // INDEX 작업
m_pFreeRoom = pIndex; // 다음 연결을 위한 세팅
#ifdef _DEBUG
// 각 블럭 마다 ExBlockSize의 부분에 데이타 세팅 작업
if( m_nAllocBufferSize )
memset((PVOID)( (DWORD)pIndex+sizeof(INDEX)+sizeof(TYPE)),
(i%10+'0'),
m_nAllocBufferSize );
#endif
// 다음 리스트로 C8List 포인트 이동
pIndex = (INDEX*)((DWORD)pIndex - m_nPerPacketSize);
}
}
template <class TYPE>
NFMemPool<TYPE>::~NFMemPool()
{
if(NULL != m_pPakets) VirtualFree( m_pPakets, 0, MEM_RELEASE );
}
template <class TYPE>
TYPE* NFMemPool<TYPE>::Alloc()
{
// 변수 초기화
INDEX* pIndex = NULL;
TYPE* pType = NULL;
Nave::NFSyncLock CL(&m_Sync);
pIndex = m_pFreeRoom;
if( pIndex != NULL )
{
// 빈공간 이동 인덱스 포인터를 다음 인덱스로 이동
m_pFreeRoom = m_pFreeRoom->pNext;
m_nCount++; // 카운트 증가
// 지정한 인덱스 포인터에서 템플릿 타입 위티 포인터 반환
pType = (TYPE*)(pIndex+1);
///////////////////////////////////////////
// 치명적인 에러 발생
// assert( m_nCount > 0 ); // make sure we don't overflow
if(m_nCount > m_nTotalCnt)
{
LOG_ERROR((L"[%s] MemPool Alloc Overflow Count(%d) >= %d", m_strLogTitle, m_nCount, m_nTotalCnt));
return NULL;
}
}
else
LOG_ERROR((L"[%s] MemPool Alloc m_pFreeRoom = NULL, Count(%d)", m_strLogTitle, m_nCount));
return pType; // 템플릿 타입 반환
}
template <class TYPE>
BOOL NFMemPool<TYPE>::Free( TYPE *ptr )
{
Nave::NFSyncLock CL(&m_Sync);
BOOL bRet = FALSE;
INDEX* pIndex = ((INDEX*)(ptr))-1; // 사용 패킷의 인덱스 포인터 얻기
// 사용중인 패킷이 있다면
if( m_nCount > 0 )
{
// 빈공간 인덱스 포인터를 앞으로 당기는 루틴
pIndex->pNext = m_pFreeRoom;
m_pFreeRoom = pIndex;
m_nCount--; // 사용 패킷수 1 감소
bRet = TRUE; // 정상 처리 알림
}
else
LOG_ERROR((L"[%s] MemPool Free Faild Count(%d) <= 0", m_strLogTitle, m_nCount));
return bRet; // 정상 처리 유무 반환
}
template <class TYPE>
INT NFMemPool<TYPE>::GetCount()
{
Nave::NFSyncLock CL(&m_Sync);
INT nRet = m_nCount; // 변수 설정
return nRet; // 반환
}
template <class TYPE>
INT NFMemPool<TYPE>::GetEmpty()
{
Nave::NFSyncLock CL(&m_Sync);
INT nRet = m_nTotalCnt - m_nCount; // 설정
return nRet; // 반환
}
template <class TYPE>
INT NFMemPool<TYPE>::GetIndex( TYPE *ptr )
{
Nave::NFSyncLock CL(&m_Sync);
INT nRet = 0; // 변수 초기화
INDEX* pIndex = ((INDEX*)(ptr))-1; // 인데스 포인터 얻기
nRet = pIndex->nIndex; // 변수 설정
return nRet; // 반환
}
}