在數據結構【二】:簡單阻塞隊列BlockingQueue的基礎上添加權限屬性:priority,並控制enqueue時根據priority排序插入.html
1.定義priority取值範圍0~9node
2.dequeue取出priority值最大的節點(最高進先出 largest-in,first-out ).數據結構
3.若priority相等,則繼續遵循FIFO原則學習
注意 : 此代碼未經生產環境檢驗,僅供學習參考.測試
PriorityQueue.hspa
#ifndef CUR_PRIORITYQUEUE_H #define CUR_PRIORITYQUEUE_H #include <stdlib.h> #include <pthread.h> struct node{ int value; int priority; //優先級,取值範圍0~9 struct node * next; }; typedef struct PriorityQueue_ST{ int capacity,remaining,closed; struct node * head, *tail; pthread_mutex_t queue_mutex; pthread_cond_t cond_not_full; pthread_cond_t cond_not_empty; pthread_cond_t cond_empty; }PriorityQueue; extern PriorityQueue* empty_queue(int _capacity); extern int queue_free(PriorityQueue *q); extern int is_empty(const PriorityQueue *q); extern int is_full(const PriorityQueue *q); extern int enqueue(struct node *item, PriorityQueue *q); extern struct node* dequeue(PriorityQueue *q); #endif
PriorityQueue.c線程
#include "PriorityQueue.h" #include <stdio.h> PriorityQueue* empty_queue(int _capacity) { PriorityQueue *q = malloc(sizeof(PriorityQueue)); q->head = q->tail = NULL; q->capacity = q->remaining = _capacity; q->closed = 0; pthread_mutex_init(&q->queue_mutex , NULL); pthread_cond_init(&q->cond_not_full , NULL); pthread_cond_init(&q->cond_not_empty , NULL); pthread_cond_init(&q->cond_empty , NULL); return q; } int queue_free(PriorityQueue *q) { pthread_mutex_lock(&q->queue_mutex); printf("close queue...\n"); q->closed = 1; //等待cond_empty while(!is_empty(q)) { pthread_cond_wait(&q->cond_empty, &q->queue_mutex); } free(q); pthread_mutex_unlock(&q->queue_mutex); printf("closed...\n"); } int is_empty(const PriorityQueue *q) { return q->capacity == q->remaining; } int is_full(const PriorityQueue *q) { return q->remaining == 0; } int enqueue(struct node *item, PriorityQueue *q) { if(q->closed) goto err; //lock pthread_mutex_lock(&q->queue_mutex); //等待cond_not_full while(is_full(q)) { pthread_cond_wait(&q->cond_not_full, &q->queue_mutex); } //設置最權限:大爲9,最小爲0,默認爲0 item->priority = item->priority > 9 ? 9 : item->priority; item->priority = item->priority < 0 ? 0 : item->priority; if(is_empty(q)) { q->head = q->tail = item; //通知全部等待cond_not_empty的線程 pthread_cond_broadcast(&q->cond_not_empty); } else { //插入時按優先級排序 : order by priority desc struct node *big = NULL; struct node *small = q->head; while(small != NULL && small->priority >= item->priority) { big = small; small = small->next; } if(small == NULL) { //尾部插入 : big = q->tail q->tail->next = item; q->tail = item; }else if(big == NULL) { //頭部插入 q->head = item; item->next = small; }else { //中部插入 big->next = item; item->next = small; } } q->remaining--; //unlock pthread_mutex_unlock(&q->queue_mutex); return 0; err : return -1; } struct node* dequeue(PriorityQueue *q) { //已經關閉的空隊列 if(q->closed && is_empty(q)) goto err; //lock pthread_mutex_lock(&q->queue_mutex); //空隊列,等待cond_not_empty while(!q->closed && is_empty(q)) { pthread_cond_wait(&q->cond_not_empty, &q->queue_mutex); } //take struct node * temp = q->head; q->head = q->head->next; //在未關閉隊列的狀況下,喚醒enqueue等待線程 if(!q->closed && is_full(q)) { pthread_cond_broadcast(&q->cond_not_full); //TODO 1 } q->remaining++; //喚醒關閉隊列線程 if(q->closed && is_empty(q)) { pthread_cond_signal(&q->cond_empty);//TODO 2 } //注意:TODO 1和TODO 2實際上是互斥的,不可能同時知足條件 //必須先判斷是否激活cond_not_full而後remaining++ //最後再判斷是否激活cond_empty //unlock pthread_mutex_unlock(&q->queue_mutex); return temp; err: return NULL; }
測試代碼code
#include <stdio.h> #include <stdlib.h> #include <time.h> #include "PriorityQueue.h" extern void* func_put(void* _q); PriorityQueue *q; pthread_t thread1; void main() { q = empty_queue(5); pthread_create(&thread1,NULL,func_put,(void*)q); srand((int) time(0)); int i; for(i=1; i<=10; i++) { struct node * item = (struct node *)malloc(sizeof(struct node)); item->value = i; item->next = NULL; item->priority = (0 + rand() % 10); enqueue(item,q); printf("enqueue -> value : %d, priority : %d, remaining : %d\n",i,item->priority,q->remaining); sleep(1); } queue_free(q); } void* func_put(void* _q) { PriorityQueue *q = (PriorityQueue*)_q; struct node *item; while((item = dequeue(q)) != NULL) { printf("dequeue -> value : %d, priority : %d, remaining : %d\n",item->value,item->priority,q->remaining); free(item); sleep(3); } }
測試結果:htm