EtrediaEmpires/p7lib/Sources/PacketsPool.h
legatt 32f4597c4d Base frontend module
- Naming style migrated to camel-case
- P7lib logger sources added
- Vcpkg manifest, CMake presets and build moved to root
- SDL2, Vulkan and RmlUi dependencies added
- Logger LOG macro added
- Logger  configuration
- SDL2 window configuration
- Vulkan configuration
- RmlUi configuration
- SDL event loop
2025-08-08 00:07:32 +03:00

387 lines
11 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// /
// 2012-2020 (c) Baical /
// /
// This library is free software; you can redistribute it and/or /
// modify it under the terms of the GNU Lesser General Public /
// License as published by the Free Software Foundation; either /
// version 3.0 of the License, or (at your option) any later version. /
// /
// This library is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU /
// Lesser General Public License for more details. /
// /
// You should have received a copy of the GNU Lesser General Public /
// License along with this library. /
// /
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// This header file describe buffers pool /
////////////////////////////////////////////////////////////////////////////////
#ifndef PACKETSPOOL_H
#define PACKETSPOOL_H
#include <new>
////////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool
class CBuffers_Pool
{
protected:
struct sChunk
{
tUINT8 *pData;
sChunk *pNext;
sChunk()
{
pData = NULL;
pNext = NULL;
}
};
//put volatile variables at the top, to obtain 32 bit alignment.
//Project has 8 tUINT8s alignment by default
volatile tINT32 m_lReference_Count;
volatile tUINT32 m_dwSize;
volatile tUINT32 *m_pSize;
tUINT32 m_dwMax_Size;
tUINT32 m_dwChunk_Size;
tUINT32 m_dwPacket_Size;
CBList<CTPacket*> m_cBuffers;
tUINT32 m_dwCount;
tUINT32 m_dwMax_Count;
tUINT32 m_dwExtracted;
tUINT32 m_dwBuffer_Size;
tLOCK m_hCS;
IJournal *m_pLog;
tUINT32 m_dwID;
tBOOL m_bInitialized;
sChunk *m_pChunk_First;
public:
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::CBuffers_Pool
CBuffers_Pool(IJournal *i_pLog,
tUINT32 i_dwChunk_Size,
tUINT32 i_dwMax_Size,
tUINT32 i_dwBuffer_Size,
tUINT32 i_dwID
)
: m_lReference_Count(0)
, m_dwSize(0)
, m_pSize(&m_dwSize)
, m_dwMax_Size(i_dwMax_Size)
, m_dwChunk_Size(i_dwChunk_Size)
, m_dwPacket_Size(0)
, m_dwCount(0)
, m_dwMax_Count(0)
, m_dwExtracted(0)
, m_dwBuffer_Size(i_dwBuffer_Size)
, m_pLog(i_pLog)
, m_dwID(i_dwID)
, m_bInitialized(TRUE)
, m_pChunk_First(NULL)
{
if (m_pLog)
{
m_pLog->Add_Ref();
}
LOCK_CREATE(m_hCS);
m_dwPacket_Size = sizeof(CTPacket) + i_dwBuffer_Size;
m_dwChunk_Size = ((m_dwChunk_Size / m_dwPacket_Size) + 1) * m_dwPacket_Size;
m_dwMax_Count = i_dwMax_Size / m_dwPacket_Size;
//m_bInitialized = Allocate(m_dwChunk_Size);
}//CBuffers_Pool::CBuffers_Pool
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::~CBuffers_Pool
~CBuffers_Pool()
{
if (m_dwExtracted)
{
JOURNAL_ERROR(m_pLog,
TM("%d buffers are missed !."),
(tUINT32)m_dwExtracted
);
}
if (0 < Get_Reference_Count())
{
JOURNAL_ERROR(m_pLog, TM("Reference count is greater than 0 !"));
}
m_cBuffers.Clear(FALSE);
sChunk *l_pNext = NULL;
while (m_pChunk_First)
{
l_pNext = m_pChunk_First->pNext;
if (m_pChunk_First->pData)
{
delete [] m_pChunk_First->pData;
}
delete m_pChunk_First;
m_pChunk_First = l_pNext;
}
if (m_pLog)
{
m_pLog->Release();
m_pLog = NULL;
}
LOCK_DESTROY(m_hCS);
}//CBuffers_Pool::~CBuffers_Pool
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Allocate
tBOOL Allocate(tUINT32 i_dwSize)
{
CTPacket *l_pPacket = NULL;
sChunk *l_pChunk = NULL;
tUINT8 *l_pData = NULL;
if ((*m_pSize) >= m_dwMax_Size)
{
JOURNAL_ERROR(m_pLog,
TM("Failed, Memory limit is reached, ID = %d Count = %d, Max = %d. Buffer Size = %d, Memory limit = %d"),
(tUINT32)m_dwID,
(tUINT32)m_dwCount,
(tUINT32)m_dwMax_Count,
(tUINT32)m_dwBuffer_Size,
(tUINT32)m_dwMax_Size
);
return FALSE;
}
if (NULL == (l_pChunk = new sChunk()))
{
JOURNAL_ERROR(m_pLog, TM("Buffer allocation failed."));
return FALSE;
}
l_pChunk->pData = new tUINT8[i_dwSize];
if (NULL == l_pChunk->pData)
{
JOURNAL_ERROR(m_pLog, TM("Buffer allocation failed."));
delete l_pChunk;
return FALSE;
}
LOCK_ENTER(m_hCS);
l_pChunk->pNext = m_pChunk_First;
m_pChunk_First = l_pChunk;
l_pData = l_pChunk->pData;
ATOMIC_ADD((volatile tINT32*)m_pSize, i_dwSize);
for (tUINT32 l_dwI = 0; l_dwI < (i_dwSize / m_dwPacket_Size); l_dwI++)
{
l_pPacket = new (l_pData) CTPacket(l_pData + sizeof(CTPacket),
m_dwBuffer_Size,
m_dwID
);
l_pData += m_dwPacket_Size;
m_cBuffers.Add_After(m_cBuffers.Get_Last(), l_pPacket);
m_dwCount ++;
}
LOCK_EXIT(m_hCS);
return TRUE;
}//CBuffers_Pool::Allocate
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Initialized
tBOOL Get_Initialized()
{
return m_bInitialized;
}//CBuffers_Pool::Get_Initialized
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Buffer_Size
tUINT32 Get_Buffer_Size()
{
return m_dwBuffer_Size;
}//CBuffers_Pool::Get_Buffer_Size
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Max_Size
tUINT32 Get_Max_Size()
{
return m_dwMax_Size;
}
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Free_Count
tUINT32 Get_Free_Count()
{
tUINT32 l_dwReturn = 0;
LOCK_ENTER(m_hCS);
l_dwReturn = m_dwMax_Count - m_dwExtracted;
LOCK_EXIT(m_hCS);
return l_dwReturn;
}//CBuffers_Pool::Get_Free_Count
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Memory_Info
void Get_Memory_Info(tUINT32 *o_dwUsed,
tUINT32 *o_dwFree,
tUINT32 *o_pAllocated
)
{
LOCK_ENTER(m_hCS);
if (o_dwUsed)
{
*o_dwUsed = m_dwExtracted * m_dwBuffer_Size;
}
if (o_dwFree)
{
*o_dwFree = (m_dwMax_Count - m_dwExtracted) * m_dwBuffer_Size;
}
if (o_pAllocated)
{
*o_pAllocated = *m_pSize;
}
LOCK_EXIT(m_hCS);
}//CBuffers_Pool::Get_Memory_Info
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Pull_Buffer
CTPacket *Pull_Buffer()
{
CTPacket *l_pReturn = NULL;
pAList_Cell l_pCell = NULL;
LOCK_ENTER(m_hCS);
if (0 >= m_cBuffers.Count())
{
Allocate(m_dwChunk_Size);
}
l_pCell = m_cBuffers.Get_First();
if (l_pCell)
{
l_pReturn = m_cBuffers.Get_Data(l_pCell);
m_cBuffers.Del(l_pCell, FALSE);
m_dwExtracted ++;
}
LOCK_EXIT(m_hCS);
return l_pReturn;
}//CBuffers_Pool::Pull_Buffer
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Push_Buffer
void Push_Buffer(CTPacket *i_pBuffer)
{
if ( (NULL == i_pBuffer)
|| (0 == m_dwExtracted)
)
{
JOURNAL_ERROR(m_pLog, TM("Wrong parameters."));
return;
}
LOCK_ENTER(m_hCS);
m_cBuffers.Add_After(m_cBuffers.Get_Last(), i_pBuffer);
m_dwExtracted --;
LOCK_EXIT(m_hCS);
}//CBuffers_Pool::Push_Buffer
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Inc_Reference_Count
tINT32 Inc_Reference_Count()
{
tINT32 l_lReturn = 0;
LOCK_ENTER(m_hCS);
m_lReference_Count ++;
l_lReturn = m_lReference_Count;
LOCK_EXIT(m_hCS);
return l_lReturn;
}//CBuffers_Pool::Inc_Reference_Count
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Dec_Reference_Count
tINT32 Dec_Reference_Count()
{
tINT32 l_lReturn = 0;
LOCK_ENTER(m_hCS);
m_lReference_Count --;
l_lReturn = m_lReference_Count;
LOCK_EXIT(m_hCS);
return l_lReturn;
}//CBuffers_Pool::Dec_Reference_Count
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Get_Reference_Count
tINT32 Get_Reference_Count()
{
tINT32 l_lReturn = 0;
LOCK_ENTER(m_hCS);
l_lReturn = m_lReference_Count;
LOCK_EXIT(m_hCS);
return l_lReturn;
}//CBuffers_Pool::Get_Reference_Count
////////////////////////////////////////////////////////////////////////////
//CBuffers_Pool::Set_External_Size
void Set_External_Size(volatile tUINT32 *i_pSize)
{
LOCK_ENTER(m_hCS);
m_pSize = i_pSize;
LOCK_EXIT(m_hCS);
}//CBuffers_Pool::Set_External_Size
};
#endif //PACKETSPOOL_H