//////////////////////////////////////////////////
//Title    : pool.c
//Auhtor   : Liu Wei
//Desc     : List and Pool Queue struct implement  
//Created  : 2007-05-01
//Revision :
//
//Revision :
//
//////////////////////////////////////////////////

#include "./include/sccp_pub.h"

/*@ignore@*/
///////////////////////////////////////////////////////////////////////////
//  Reserved for Pool Test  -- Start
///////////////////////////////////////////////////////////////////////////
/*
   #include "stdio.h"
   #include "string.h"
   #include "malloc.h"

   typedef struct SP_PriPoolEle
   {
   char ch;
   }
   SP_PriPoolEle;
 */
///////////////////////////////////////////////////////////////////////////
//   Reserved for Pool Test  -- End                                                            
///////////////////////////////////////////////////////////////////////////
#define SP_MAX_ELEMENT 512

CO_Pool tInCoPool;
CO_Pool *pInCoPool;
CO_Pool tOutCoPool[SP_POOL_SIZE];
CO_Pool *pOutCoPool[SP_POOL_SIZE];


//add by roy jiang for a replacement of dynamic memory allocation
CO_PoolEle SpEleBuf[SP_MAX_ELEMENT];

void spPoolInit (  )
{    
    int i;
	pInCoPool = &tInCoPool;
	for (i = 0; i < SP_POOL_SIZE; i++)
    	pOutCoPool[i] = &tOutCoPool[i];
	memset ( pInCoPool, 0, sizeof ( CO_Pool ) );
	memset ( tOutCoPool, 0, sizeof ( CO_Pool ) * SP_POOL_SIZE );
	memset ( SpEleBuf, 0, sizeof ( CO_PoolEle ) * SP_MAX_ELEMENT );
	POOL_INIT ( &pInCoPool->tPoolHead );
	pInCoPool->pPoolHead = &pInCoPool->tPoolHead;
	pInCoPool->uMaxPoolSize = MAX_IN_POOL;
	for (i = 0; i < SP_POOL_SIZE; i++)
	{
		POOL_INIT ( &pOutCoPool[i]->tPoolHead );    
		pOutCoPool[i]->pPoolHead = &pOutCoPool[i]->tPoolHead;
		pOutCoPool[i]->uMaxPoolSize = MAX_OUT_POOL;
	}    
}

static int busyCount = 0;
CO_PoolEle *spMallocEle()
{
	static int i = 0;
	int j = i;

	if (busyCount >= SP_MAX_ELEMENT)
		return NULL;	

	while (++i != j)
	{
		if (i >= SP_MAX_ELEMENT)
			i = 0;
		
		if (SpEleBuf[i].flag == 0)
		{
			busyCount++;
			SpEleBuf[i].flag = 1;
			pSp->tCo.tCoDebugStatic.dbusyElem = busyCount;
			return &SpEleBuf[i];
		}		
	}

	return NULL;
}

void spFreeEle(CO_PoolEle *elem)
{
	if (elem->flag != 0)
	{
		busyCount--;
		pSp->tCo.tCoDebugStatic.dbusyElem = busyCount;
		memset ( elem, 0, sizeof ( CO_PoolEle ) );
	}	
	return;
}

int spPoolGet ( SP_PriPoolEle *pPri, CO_Pool *pCoPool )
{
    CO_PoolEle *pPoolEle;

    spWatchDogStatic ( CO_GET_POOL );

    if( pCoPool->uPoolCount <= 0 || ( POOL_EMPTY ( pCoPool->pPoolHead ) ) )
    {
        //spLogDebug ( SCCPDB_ERR ,"SCCP get primitive pool fail ,empty" );
        return 0;
    }

    memcpy ( pPri, &pCoPool->pPoolHead->pPoolFirst->tPri, sizeof ( SP_PriPoolEle ) );
    pPoolEle = pCoPool->pPoolHead->pPoolFirst;
    POOL_REMOVE ( pCoPool->pPoolHead, pPoolEle, tPointer );
    pCoPool->uPoolCount--;
 //   free ( pPoolEle );
	spFreeEle (pPoolEle);
    spWatchDogStatic ( CO_READ_POOL );
    
    return 1;
}

int spPoolPut ( SP_PriPoolEle * pPri, CO_Pool * pCoPool )
{
    CO_PoolEle *pPoolEle;

    spWatchDogStatic ( PUT_ELE_APT );

    if( pCoPool->uPoolCount > pCoPool->uMaxPoolSize )
    {
        spLogDebug ( SCCPDB_ERR, "SCCP put Primitive Pool fail , pool full" );
        return 0;
    }

//commentted by roy jiang to disable dynamic memory allocation, 07-11-16
//	pPoolEle = ( CO_PoolEle * ) malloc ( sizeof ( CO_PoolEle ) );	
	pPoolEle = spMallocEle();
    if( NULL == pPoolEle )
    {
        spLogDebug ( SCCPDB_ERR, "SCCP put Primitive Pool fail ,allocate memery fail" );
        return 0;
    }

    memcpy ( &pPoolEle->tPri, pPri, sizeof ( SP_PriPoolEle ) );
    POOL_INSERT_TAIL ( pCoPool->pPoolHead, pPoolEle, tPointer );
    pCoPool->uPoolCount++;

	spWatchDogStatic ( PUT_ELE_SUC );
    return 1;
}

///////////////////////////////////////////////////////////////////////////
//  Reserved for Pool Test  -- Start
///////////////////////////////////////////////////////////////////////////
/*
   FILE *fp;   

   int main()
   {
   int           nCh;
   CO_PoolEle pOutGetPri;
   CO_PoolEle pInGetPri;
   CO_PoolEle pOutPutPri;
   CO_PoolEle pInPutPri;
   CO_PoolEle *pPri;

   fp = fopen("log.txt"  ,"w+");
   if( NULL ==fp )
   {
   return 0;
   }
   spPoolInit();

   pOutGetPri.tPri.ch = pInGetPri.tPri.ch = '0';

   for( nCh = 0 ; nCh < 32 ; nCh ++ )
   {
   memset(&pOutGetPri , 0 , sizeof(CO_PoolEle));
   memset(&pInGetPri , 0 , sizeof(CO_PoolEle));
   memset(&pOutPutPri , 0 , sizeof(CO_PoolEle));
   memset(&pInPutPri , 0 , sizeof(CO_PoolEle));

   pOutPutPri.tPri.ch = 'A' + nCh;
   spPoolPut( &pOutPutPri.tPri , pOutCoPool);

   pInPutPri.tPri.ch = 'Z' - nCh;
   spPoolPut( &pInPutPri.tPri , pInCoPool);

   if( nCh && (nCh % 4 == 0) )
   {
   spPoolGet( &pOutGetPri.tPri , pOutCoPool);
   }

   if( nCh && (nCh % 6 ==  0 ) )
   {
   spPoolGet( &pInGetPri.tPri , pInCoPool);
   }

   fprintf( fp ,"\npOutPoolHead: [%d]\n" , pOutCoPool->uPoolCount);
   fprintf( fp ,"  Out Put : %c\n" , pOutPutPri.tPri.ch);
   fprintf( fp ,"  Out Get : %c\n" , pOutGetPri.tPri.ch);
   fprintf( fp ,"  List :");

   POOL_FOREACH( pPri , pOutCoPool->pPoolHead , tPointer  )
   {
   fprintf( fp ,"%c " ,pPri->tPri.ch );
   }
   fprintf( fp ,"\n");

   fprintf( fp ,"\npInPoolHead:  [%d]\n" , pInCoPool->uPoolCount);
   fprintf( fp ,"  Put : %c\n" , pInPutPri.tPri.ch);
   fprintf( fp ,"  Get : %c\n" , pInGetPri.tPri.ch);
   fprintf( fp ,"  List :");
   POOL_FOREACH( pPri , pInCoPool->pPoolHead , tPointer  )
   {
   fprintf( fp ,"%c " ,pPri->tPri.ch );
   }
   fprintf( fp ,"\n\n\n");

   }
   fclose(fp);
   getchar();
   return 1;

   }
 */
///////////////////////////////////////////////////////////////////////////
//   Reserved for Pool Test  -- End                                                            
///////////////////////////////////////////////////////////////////////////

/*@end@*/
