//muqueue.c
#include "myqueue.h"

ArrQueue *CreateQueue( int nLen )
{
    ArrQueue *pQueue = (ArrQueue *)malloc( sizeof(ArrQueue) );
    pQueue->rear = (ElemType **)calloc( nLen, sizeof(ElemType **) );
    pQueue->front = pQueue->rear[0];
    pQueue->len = 0;
    pQueue->size = nLen;
 
	pthread_mutex_init(&pQueue->locker,NULL);
	pthread_cond_init(&pQueue->notEmpty,NULL);
	pthread_cond_init(&pQueue->notFull,NULL);
 
    return pQueue;
}
 
void DestroyQueue( ArrQueue *pQueue )
{
    free( pQueue->rear );
    free( pQueue );
 
	pthread_mutex_destroy(&pQueue->locker);
	pthread_cond_destroy(&pQueue->notEmpty);
	pthread_cond_destroy(&pQueue->notFull);
 
    pQueue = NULL;
}
 
void ClearQueue( ArrQueue *pQueue )
{
    pQueue->front = pQueue->rear[0];
 
    pQueue->len = 0;
}
 
 
int GetLength( ArrQueue *pQueue )
{
    return pQueue->len;
}
 
 
int GetSize( ArrQueue *pQueue )
{
    return pQueue->size;
}
 
int IsEmpty( ArrQueue *pQueue )
{
    return pQueue->len == 0 ? TRUE : FALSE;
}
 
int IsFull( ArrQueue *pQueue )
{
//DBG("pQueue->len=%d,pQueue->size=%d\n",pQueue->len,pQueue->size);
    return pQueue->len == pQueue->size? TRUE : FALSE;
}
 
int GetHead( ArrQueue *pQueue, ElemType **pe )
{
    if( pQueue->len == 0 )
    {
        *pe = NULL;
        return -1;
    }
 
    *pe = pQueue->rear[pQueue->len-1];
 
    return pQueue->len-1;
}
 
int EnQueue( ArrQueue *pQueue, ElemType *pe )
{
    pthread_mutex_lock(&pQueue->locker);
 
	while (IsFull(pQueue))
	{
		//DBG("\n");
		pthread_cond_wait(&pQueue->notFull, &pQueue->locker);
	} 
 
    int i = 0;
    for( i = pQueue->len; i > 0; --i )
    {
        pQueue->rear[i] = pQueue->rear[i-1];
    }
    pQueue->rear[0] = pe;
    pQueue->front = pQueue->rear[pQueue->len];
 
     ++pQueue->len;
 
	pthread_cond_signal(&pQueue->notEmpty);
	pthread_mutex_unlock(&pQueue->locker);
    
    return pQueue->len;
}
 
int DeQueue( ArrQueue *pQueue, ElemType **pe )
{
 
	pthread_mutex_lock(&pQueue->locker);
	while (IsEmpty(pQueue))
	{
		pthread_cond_wait(&pQueue->notEmpty, &pQueue->locker);
	}
 
 
	if( pQueue->len == 0 )
	{
		*pe = NULL;
		return -1;
	}
 
	*pe = pQueue->front;
 
//DBG("len= %d,%x \n",(*pe)->len,(*pe)->len);
 
	--pQueue->len;
	pQueue->front = pQueue->rear[pQueue->len-1];
 
	pthread_cond_signal(&pQueue->notFull); 
	pthread_mutex_unlock(&pQueue->locker);
 
    return pQueue->len;
}
 
 
void ForEachQueue( ArrQueue *pQueue, void (*func)(ElemType *pe) )
{
    int i = 0;
    for( i = 0; i < pQueue->len; ++i )
    {
        func( pQueue->rear[i] );
    }
}