#include "StdAfx.h"
#include <assert.h>
#include "packetspool.h"


CPacketsPool::CPacketsPool(void)
{
	m_pPool=NULL;
	m_pFirst=NULL;
	m_pLast=NULL;
	m_dwPoolSize=0;
	m_dwNumOfPackets=0;
	::InitializeCriticalSection(&m_cs);
}

CPacketsPool::~CPacketsPool(void)
{
	Shutdown();
	::DeleteCriticalSection(&m_cs);
}

void CPacketsPool::Init(DWORD dwPoolSize)
{
	m_pPool=new _Packet[dwPoolSize];
	memset(m_pPool,0,sizeof(_Packet)*dwPoolSize);
	for(int i=dwPoolSize-1;i>=0;i--)
	{
		m_stkFreePackets.push(&m_pPool[i]);
	}
	m_pFirst=NULL;
}

void CPacketsPool::Shutdown()
{
	if(m_pPool)
	{
		delete[] m_pPool;
	}
	m_pFirst=NULL;
	m_pLast=NULL;
	m_dwPoolSize=0;
	m_dwNumOfPackets=0;
	while(m_stkFreePackets.size())
		m_stkFreePackets.pop();
}

void CPacketsPool::PushPacket(BYTE *pBuf,DWORD dwSize)
{
	//printf("push\n");
	_XCriticalSection _cs(&m_cs);
	if(m_stkFreePackets.empty())
		DebugBreak();
	_Packet *pFirstFree=m_stkFreePackets.top();
	memcpy(pFirstFree->cData,pBuf,dwSize);
	pFirstFree->dwSize=dwSize;
	m_stkFreePackets.pop();
	//times
	pFirstFree->dwTimestamp=::GetTickCount();
	if(m_dwNumOfPackets)
	{
		m_pLast->next=pFirstFree;
		pFirstFree->prev=m_pLast;
		m_pLast=pFirstFree;
		pFirstFree->next=NULL;
	}
	else
	{
		//if there isn't a last also the first must be NULL
		assert(!m_pFirst);
		assert(!m_pLast);
		m_pFirst=pFirstFree;
		m_pLast=pFirstFree;
		pFirstFree->prev=pFirstFree->next=NULL;
	}
	
	m_dwNumOfPackets++;
}

DWORD CPacketsPool::PopPacket(BYTE *pBuf)
{
	_XCriticalSection _cs(&m_cs);
	if(!m_dwNumOfPackets)return 0;
	_Packet *p=m_pFirst;
	memcpy(pBuf,p->cData,p->dwSize);
	m_pFirst=p->next;
	if(m_pFirst==NULL)
	{
        m_pLast=NULL;
	}
	else
	{
		m_pFirst->prev=NULL;
	}
	p->next=p->prev=NULL;
	//the packet is free again
	m_stkFreePackets.push(p);
	m_dwNumOfPackets--;
	return p->dwSize;
}

DWORD CPacketsPool::GetPacketAge()
{
	if(!m_pFirst)return 0;
	return ::GetTickCount()-m_pFirst->dwTimestamp;
}