1 //初始化循环队列
2 void InitQue(PT_QUEUE ptQue)
3 {
4 memset(ptQue, 0, sizeof(*ptQue));
5 }
6
7 //向循环队列中插入元素
8 void EnterQue(PT_QUEUE ptQue, int dwElem)
9 {
10 if(IsQueFull(ptQue))
11 {
12 printf("Elem %d cannot enter Queue %p(Full)!\n", dwElem, ptQue);
13 return;
14 }
15 ptQue->aData[ptQue->dwTail]= dwElem;
16 ptQue->dwTail = (ptQue->dwTail + 1) % QUEUE_SIZE;
17 }
18
19 //从循环队列中取出元素
20 int LeaveQue(PT_QUEUE ptQue)
21 {
22 if(IsQueEmpty(ptQue))
23 {
24 printf("Queue %p is Empty!\n", ptQue);
25 return -1;
26 }
27 int dwElem = ptQue->aData[ptQue->dwHead];
28 ptQue->dwHead = (ptQue->dwHead + 1) % QUEUE_SIZE;
29 return dwElem;
30 }
31
32 //从队首至队尾依次显示队中元素值
33 void DisplayQue(PT_QUEUE ptQue)
34 {
35 if(IsQueEmpty(ptQue))
36 {
37 printf("Queue %p is Empty!\n", ptQue);
38 return;
39 }
40
41 printf("Queue Element: ");
42 int dwIdx = ptQue->dwHead;
43 while((dwIdx % QUEUE_SIZE) != ptQue->dwTail)
44 printf("%d ", ptQue->aData[(dwIdx++) % QUEUE_SIZE]);
45
46 printf("\n");
47 }
|
1 //判断循环队列是否为空
2 int IsQueEmpty(PT_QUEUE ptQue)
3 {
4 return ptQue->dwHead == ptQue->dwTail;
5 }
6
7 //判断循环队列是否为满
8 int IsQueFull(PT_QUEUE ptQue)
9 {
10 return (ptQue->dwTail + 1) % QUEUE_SIZE == ptQue->dwHead;
11 }
12
13 //获取循环队列元素数目
14 int QueDataNum(PT_QUEUE ptQue)
15 {
16 return (ptQue->dwTail - ptQue->dwHead + QUEUE_SIZE) % QUEUE_SIZE;
17 }
18
19 //获取循环队列队首位置
20 int GetQueHead(PT_QUEUE ptQue)
21 {
22 return ptQue->dwHead;
23 }
24 //获取循环队列队首元素
25 int GetQueHeadData(PT_QUEUE ptQue)
26 {
27 return ptQue->aData[ptQue->dwHead];
28 }
29 //获取循环队列队尾位置
30 int GetQueTail(PT_QUEUE ptQue)
31 {
32 return ptQue->dwTail;
33 }
|
1 static T_QUEUE gtQueue;
2 void QueueTest(void)
3 {
4 InitQue(>Queue);
5 printf("Enter Queue 1,2,3,4,5...\n");
6 EnterQue(>Queue, 1);
7 EnterQue(>Queue, 2);
8 EnterQue(>Queue, 3);
9 EnterQue(>Queue, 4);
10 EnterQue(>Queue, 5);
11 printf("Queue Status: Empty(%d), Full(%d)\n", IsQueEmpty(>Queue), IsQueFull(>Queue));
12 printf("Queue Elem Num: %u\n", QueDataNum(>Queue));
13 printf("Head: %u(%d)\n", GetQueHead(>Queue), GetQueHeadData(>Queue));
14 printf("Tail: %u\n", GetQueTail(>Queue));
15 DisplayQue(>Queue);
16
17 printf("\nLeave Queue...\n");
18 printf("Leave %d\n", LeaveQue(>Queue));
19 printf("Leave %d\n", LeaveQue(>Queue));
20 printf("Leave %d\n", LeaveQue(>Queue));
21 DisplayQue(>Queue);
22
23 printf("\nEnter Queue 6,7...\n");
24 EnterQue(>Queue, 6);
25 EnterQue(>Queue, 7);
26 DisplayQue(>Queue);
27
28 printf("\nLeave Queue...\n");
29 printf("Leave %d\n", LeaveQue(>Queue));
30 printf("Leave %d\n", LeaveQue(>Queue));
31 printf("Leave %d\n", LeaveQue(>Queue));
32 DisplayQue(>Queue);
33 }
|
1 Enter Queue 1,2,3,4,5...
2 Elem 5 cannot enter Queue 0x8053f9c(Full)!
3 Queue Status: Empty(0), Full(1)
4 Queue Elem Num: 4
5 Head: 0(1)
6 Tail: 4
7 Queue Element: 1 2 3 4
8
9 Leave Queue...
10 Leave 1
11 Leave 2
12 Leave 3
13 Queue Element: 4
14
15 Enter Queue 6,7...
16 Queue Element: 4 6 7
17
18 Leave Queue...
19 Leave 4
20 Leave 6
21 Leave 7
22 Queue 0x8053f9c is Empty!
|
1 int main(void)
2 {
3 InitQue(>Queue);
4 srand(getpid()); //初始化随机函数发生器
5
6 pthread_t aThrd[CONSUMER_NUM+PRODUCER_NUM];
7 int dwThrdIdx;
8 for(dwThrdIdx = 0; dwThrdIdx < CONSUMER_NUM; dwThrdIdx++)
9 { //创建CONSUMER_NUM个消费者线程,传入(void*)dwThrdIdx作为ConsumerThread的参数
10 pthread_create(&aThrd[dwThrdIdx], NULL, ConsumerThread, (void*)dwThrdIdx);
11 }
12 sleep(2);
13 for(dwThrdIdx = 0; dwThrdIdx < PRODUCER_NUM; dwThrdIdx++)
14 {
15 pthread_create(&aThrd[dwThrdIdx], NULL, ProducerThread, (void*)dwThrdIdx);
16 }
17 while(1);
18 return 0 ;
19 }
|
1 void *ProducerThread(void *pvArg)
2 {
3 pthread_detach(pthread_self());
4 int dwThrdNo = (int)pvArg;
5 while(1)
6 {
7 pthread_mutex_lock(>QueLock);
8 while(IsQueFull(>Queue)) //队列由满变为非满时,生产者线程被唤醒
9 pthread_cond_wait(>PrdCond, >QueLock);
10
11 EnterQue(>Queue, GetQueTail(>Queue)); //将队列元素下标作为元素值入队
12 if(QueDataNum(>Queue) == 1) //当生产者开始产出后,通知(唤醒)消费者线程
13 pthread_cond_broadcast(>CsmCond);
14 printf("[Producer %2u]Current Product Num: %u\n", dwThrdNo, QueDataNum(>Queue));
15
16 pthread_mutex_unlock(>QueLock);
17 sleep(rand()%DELAY_TIME + 1);
18 }
19 }
队列变满时,生产者线程进入休眠状态。消费者线程取出产品,将队列由满变为非满时,生产者线程再次被唤醒。
消费者线程启动例程ConsumerThread()实现如下:
1 void *ConsumerThread(void *pvArg)
2 {
3 pthread_detach(pthread_self());
4 int dwThrdNo = (int)pvArg;
5 while(1)
6 {
7 pthread_mutex_lock(>QueLock);
8 while(IsQueEmpty(>Queue)) //队列由空变为非空时,消费者线程将被唤醒
9 pthread_cond_wait(>CsmCond, >QueLock);
10
11 if(GetQueHead(>Queue) != GetQueHeadData(>Queue))
12 {
13 printf("[Consumer %2u]Product: %d, Expect: %d\n", dwThrdNo,
14 GetQueHead(>Queue), GetQueHeadData(>Queue));
15 exit(0);
16 }
17 LeaveQue(>Queue);
18 if(QueDataNum(>Queue) == (PRD_NUM-1)) //当队列由满变为非满时,通知(唤醒)生产者线程
19 pthread_cond_broadcast(>PrdCond);
20 printf("[Consumer %2u]Current Product Num: %u\n", dwThrdNo, QueDataNum(>Queue));
21
22 pthread_mutex_unlock(>QueLock);
23 sleep(rand()%DELAY_TIME + 1);
24 }
25 }
|
1 #define QUEUE_SIZE 20
2 volatile unsigned int gdwPrdNum = 0, gdwCsmNum = 0;
3 int gQueue[QUEUE_SIZE] = {0};
4
5 void *Producer(void *pvArg) {
6 while(1) {
7 while(gdwPrdNum - gdwCsmNum == QUEUE_SIZE)
8 ; //Full
9
10 gQueue[gdwPrdNum % QUEUE_SIZE]++;
11 gdwPrdNum++;
12 }
13 pthread_exit(0);
14 }
15
16 void *Consumer(void *pvArg) {
17 while(1) {
18 while(gdwPrdNum - gdwCsmNum == 0)
19 ; //Empty
20
21 gQueue[gdwCsmNum % QUEUE_SIZE]--;
22 gdwCsmNum++;
23 }
24 pthread_exit(0);
25 }
|