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; i next = 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; }