www.pudn.com > pthread_examples.rar > queue.c


/* queue.c 
** Copyright 2000 Daniel Robbins, Gentoo Technologies, Inc. 
** Author: Daniel Robbins 
** Date: 16 Jun 2000 
** 
** This set of queue functions was originally thread-aware.  I 
** redesigned the code to make this set of queue routines 
** thread-ignorant (just a generic, boring yet very fast set of queue 
** routines).  Why the change?  Because it makes more sense to have 
** the thread support as an optional add-on.  Consider a situation 
** where you want to add 5 nodes to the queue.  With the 
** thread-enabled version, each call to queue_put() would 
** automatically lock and unlock the queue mutex 5 times -- that's a 
** lot of unnecessary overhead.  However, by moving the thread stuff 
** out of the queue routines, the caller can lock the mutex once at 
** the beginning, then insert 5 items, and then unlock at the end. 
** Moving the lock/unlock code out of the queue functions allows for 
** optimizations that aren't possible otherwise.  It also makes this 
** code useful for non-threaded applications. 
** 
** We can easily thread-enable this data structure by using the 
** data_control type defined in control.c and control.h.  */ 
#include  
#include  
#include "queue.h" 
 
void queue_init(void)  
{ 
	int i            = 0; 
	node* stInitNode = NULL; 
	node* stNodeTmp1 = NULL; 
	node* stNodeTmp2 = NULL; 
	iPopIndex        = 0; 
	iPushIndex       = 0; 
	pNodeHead        = NULL; 
	pQueue.head     = NULL; 
	pQueue.tail     = NULL; 
	iQueueNodeNum    = 0; 
 
	pthread_mutex_init(&pthQueueMutex, NULL); 
	sem_init(&pthSem, 0, 0); 
 
	/*一次分配100个节点*/ 
	for(i=0; inext = stNodeTmp1;	 
			stNodeTmp2       = stNodeTmp1; 
		}		 
	} 
 
	pQueue.head = pNodeHead; 
	pQueue.tail = pNodeHead; 
	return ; 
} 
 
void queue_deinit(void) 
{ 
	node* stNodeTmp = NULL;	 
	int i           = 0; 
	for(pNodeHead; pNodeHead!=NULL;) 
	{ 
		stNodeTmp = pNodeHead->next; 
		if(NULL != pNodeHead) 
		{ 
			free(pNodeHead); 
		} 
		pNodeHead = stNodeTmp; 
	} 
	pNodeHead    = NULL; 
	pQueue.head = NULL; 
	pQueue.tail = NULL;	 
	sem_destroy(&pthSem); 
	pthread_mutex_destroy(&pthQueueMutex); 
 
	return ; 
} 
 
void queue_put(queue *myroot,node *mynode)  
{ 
	if(NULL == myroot) 
	{ 
		printf("queue_put : NULL == myroot\n"); 
		exit(1); 
	} 
	if(NULL == mynode) 
	{ 
		printf("queue_put : NULL == mynode\n"); 
		return; 
	} 
 
	if(iQueueNodeNum >= MAX_QUEUE_NODE) 
	{ 
		printf("queue_put : queue is full!\n"); 
		return; 
	} 
 
	if(iPushIndex >= MAX_QUEUE_NODE) 
	{ 
		iPushIndex   = iPushIndex % 100; 
		myroot->tail = pNodeHead; 
	} 
	memcpy(myroot->tail->cNodeStr, mynode->cNodeStr, MAX_BUFFER_LEN); 
	myroot->tail = myroot->tail->next; 
	iPushIndex++; 
	 
	pthread_mutex_lock(&pthQueueMutex); 
	iQueueNodeNum++; /*对节点数的操作考虑以后加锁*/ 
	pthread_mutex_unlock(&pthQueueMutex); 
	sem_post(&pthSem); 
 
	return ; 
} 
 
node *queue_get(queue *myroot)  
{ 
	/*get from root*/ 
	if(iQueueNodeNum <= 0) 
	{ 
		printf("queue_get : queue is empty!\n"); 
	} 
	 
	sem_wait(&pthSem); 
	 
	node *mynode; 
 
	if(iPopIndex >= MAX_QUEUE_NODE) 
	{ 
		iPopIndex    = iPopIndex % 100; 
		myroot->head = pNodeHead; 
	} 
	/*已经保证了队列不为空*/ 
	mynode = myroot->head; 
	myroot->head = myroot->head->next; 
	iPopIndex++; 
	 
	pthread_mutex_lock(&pthQueueMutex); 
	iQueueNodeNum--;  /*对节点数的操作考虑以后加锁*/ 
	pthread_mutex_unlock(&pthQueueMutex); 
	 
	return mynode; 
} 
 
int getqueuesize(queue *myroot) 
{ 
	if(NULL == myroot) 
	{ 
		printf("getqueuesize : NULL == myroot \n"); 
		exit(1); 
	} 
	return iQueueNodeNum; 
} 
 
PTHBOOL isqueueempty(queue *myroot) 
{ 
	if(0 < iQueueNodeNum) 
	{ 
		return FALSE; 
	} 
	return TRUE; 
}