www.pudn.com > IOCPNet_Demo.zip > PreAllocator.cpp
////////////////////////////////////////////////////////////////////////////////////////////////////
// Module Name:
// PreAllocator.cpp
// Author:
// Chun-Hyok, Chong.
// Description:
// The module that allocates the specific sized memory before using it.
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "preallocator.h"
#include "safelocker.h"
#define DWORD_FULL 0xFFFFFFFF
void OPreAllocator::Init()
{
m_pMem = 0;
m_UnitPageSize = 0;
m_NumberOfPages = 0;
m_FreePageIndex = 0;
m_pPageInfo = 0;
m_AllocatedPageCount = 0;
InterlockedExchange((volatile long *)&m_State, 0);
m_SerialGenerator = 0;
InitializeCriticalSection(&m_CSPageInfo);
return;
} // Init()
void OPreAllocator::DeInit()
{
if (0 != m_pPageInfo)
{
VirtualFree(m_pPageInfo, 0, MEM_RELEASE);
m_pPageInfo = 0;
}
if (0 != m_pMem)
{
VirtualFree(m_pMem, 0, MEM_RELEASE);
m_pMem = 0;
}
m_UnitPageSize = 0;
m_NumberOfPages = 0;
m_FreePageIndex = 0;
m_AllocatedPageCount = 0;
DeleteCriticalSection(&m_CSPageInfo);
InterlockedExchange((volatile long *)&m_State, 0);
return;
} // DeInit()
BOOL OPreAllocator::PreAllocate(DWORD UnitPageSize, DWORD NumberOfPages)
{
DWORD Loop;
if (0 == UnitPageSize || 0 == NumberOfPages)
{
return 0;
}
if (0 != m_pMem)
{
VirtualFree(m_pMem, 0, MEM_RELEASE);
m_pMem = 0;
}
m_UnitPageSize = UnitPageSize;
m_NumberOfPages = NumberOfPages;
m_AllocatedPageCount = 0;
m_pPageInfo = (OPageInfo *)VirtualAlloc(0, m_NumberOfPages * sizeof (OPageInfo), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (0 == m_pPageInfo)
{
return 0;
}
for (Loop = 0; Loop < m_NumberOfPages; Loop++)
{
(m_pPageInfo + Loop)->bUsed = 0;
(m_pPageInfo + Loop)->Serial = 0;
}
m_pMem = (void *)VirtualAlloc(0, m_UnitPageSize * m_NumberOfPages, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (0 == m_pMem)
{
VirtualFree(m_pPageInfo, 0, MEM_RELEASE);
m_pPageInfo = 0;
return 0;
}
InterlockedExchange((volatile long *)&m_State, 1);
return 1;
} // PreAllocator()
BOOL OPreAllocator::FreePreAllocatedMemory()
{
if (0 == InterlockedExchange((volatile long *)&m_State, m_State) || 0 == m_pPageInfo || 0 == m_pMem)
{
return 0;
}
if (0 != m_pPageInfo)
{
VirtualFree(m_pPageInfo, 0, MEM_RELEASE);
m_pPageInfo = 0;
}
if (0 != m_pMem)
{
VirtualFree(m_pMem, 0, MEM_RELEASE);
m_pMem = 0;
}
m_UnitPageSize = 0;
m_NumberOfPages = 0;
m_FreePageIndex = 0;
m_AllocatedPageCount = 0;
InterlockedExchange((volatile long *)&m_State, 0);
return 1;
} // FreePreAllocatedMemory()
void *OPreAllocator::Allocate(DWORD SizeInByte)
{
DWORD PageCount;
DWORD LoopTotal;
DWORD LoopInner;
BOOL bSettable;
OSafeLocker SL(&m_CSPageInfo);
void *pResult;
DWORD Serial;
if (0 == SizeInByte) // very important checking!
{
return 0;
}
if (0 == InterlockedExchange((volatile long *)&m_State, m_State))
{
return 0;
}
pResult = 0;
PageCount = SizeInByte / m_UnitPageSize;
if (0 < SizeInByte % m_UnitPageSize)
{
PageCount++;
}
// The shape of the memory area is not ring, don't confuse.
SL.Lock();
LoopTotal = 0;
while (LoopTotal < (m_NumberOfPages + 1)) // +1 : when 1 page count, 1st allocate -> 2nd allocate. think condition (PageCount <= m_NumberOfPages - m_FreePageIndex).
{
if ((PageCount <= m_NumberOfPages - m_FreePageIndex) && (0 == (m_pPageInfo + m_FreePageIndex)->bUsed))
{
bSettable = 1;
for (LoopInner = 0; LoopInner < PageCount; LoopInner++)
{
if (1 == (m_pPageInfo + m_FreePageIndex + LoopInner)->bUsed)
{
bSettable = 0;
break;
}
}
if (0 == bSettable)
{
m_FreePageIndex += LoopInner; // more 1 added at below.
LoopTotal += LoopInner; // more 1 added at below.
}
else // if (1 == bSettable)
{
Serial = GetSerial();
for (LoopInner = 0; LoopInner < PageCount; LoopInner++)
{
(m_pPageInfo + m_FreePageIndex + LoopInner)->bUsed = 1;
(m_pPageInfo + m_FreePageIndex + LoopInner)->Serial = Serial;
m_AllocatedPageCount++;
}
pResult = (void *)(((char *)m_pMem) + (m_UnitPageSize * m_FreePageIndex));
m_FreePageIndex += PageCount;
ZeroMemory(pResult, m_UnitPageSize * PageCount);
break;
}
}
m_FreePageIndex++;
if (m_NumberOfPages <= m_FreePageIndex)
{
m_FreePageIndex = 0;
}
LoopTotal++;
}
SL.Unlock();
return pResult;
} // Allocate()
BOOL OPreAllocator::Free(void *pPointer)
{
DWORD Loop;
DWORD PageIndex;
OSafeLocker SL(&m_CSPageInfo);
DWORD Serial;
if (0 == pPointer || 0 == InterlockedExchange((volatile long *)&m_State, m_State))
{
return 0;
}
PageIndex = (DWORD)(((char *)pPointer - (char *)m_pMem) / m_UnitPageSize);
if (0 != ((char *)pPointer - (char *)m_pMem) % m_UnitPageSize)
{
return 0;
}
SL.Lock();
Loop = PageIndex;
Serial = (m_pPageInfo + Loop)->Serial;
while (m_NumberOfPages > Loop)
{
if (Serial != (m_pPageInfo + Loop)->Serial)
{
break;
}
(m_pPageInfo + Loop)->bUsed = 0;
(m_pPageInfo + Loop)->Serial = 0;
Loop++;
m_AllocatedPageCount--;
}
SL.Unlock();
return 1;
} // Free()
DWORD OPreAllocator::GetUnitPageSize()
{
return m_UnitPageSize;
} // GetUnitPageSize()
DWORD OPreAllocator::GetNumberOfPages()
{
return m_NumberOfPages;
} // GetNumberOfPages()
DWORD OPreAllocator::GetSerial()
{
DWORD Result;
Result = InterlockedIncrement((long *)&m_SerialGenerator);
return Result;
} // GetSerial()
DWORD OPreAllocator::GetUsedMemorySizeInByte()
{
OSafeLocker SL(&m_CSPageInfo);
DWORD ReturnValue;
ReturnValue = 0;
SL.Lock();
ReturnValue = m_AllocatedPageCount * m_UnitPageSize;
SL.Unlock();
return ReturnValue;
} // GetUsedMemorySizeInByte()
void *OPreAllocator::GetAllocPoint()
{
return m_pMem;
} // GetAllocPoint()