1. 程式人生 > >基於環形佇列的生產者消費者模型

基於環形佇列的生產者消費者模型

之前的Blog基於Queue的生產者消費者模型,已經談過了基於queue的生產消費模型,其空間是可以動態分配的。而現在是基於固定大小的環形佇列重寫這個程式。

基於環形佇列的生產消費模型

  • 環形佇列採用陣列模擬,用模運算來模擬環狀特性

  • 環形結構起始狀態和結束狀態都是一樣的,不好判斷為空或者為滿,所以就需要通過計數器或者標記位來判斷滿或空。另外也可以預留一個空的位置,作為滿的狀態。

 

 

  • 消費者總是跟在生產者的後邊,且不會超過生產者
  • 生產者一直在消費者的前邊,且不會超過消費者一圈。
  • head和tail指向同一個位置的時候,佇列為空。
  • 當head在tail的下一個位置時,環形佇列為滿。

 

/*#####  ringqueue.cc   ####*/
#include"test.hpp"

const int num=16;

using namespace std;

void *consume_routine(void *arg)
{	
	int d;
	RingQueue *q=(RingQueue*)arg;
	for(;;)
	{
		q->PopData(d);
		cout<<"consume done,data is..."<<d<<endl;
	}
}
void *product_routine(void *arg)
{
	RingQueue *q=(RingQueue*)arg;
	srand((unsigned long)time(NULL));
	for(;;)
	{
		int d=rand()%100+1;
		q->PushData(d);
		cout<<"Product done,data is..."<<d<<endl;
		sleep(1);
	} 
}
int main()
{
	RingQueue *q=new RingQueue(num);
	pthread_t c,p;
	pthread_create(&c,NULL,consume_routine,(void*)q);
	pthread_create(&p,NULL,product_routine,(void*)q);


	pthread_join(&c,NULL);
	pthread_join(&p,NULL);


	delete(q);



	return 0;
}
/*******   test.hpp   *******/
#ifndef __TEST_HPP__
#define __TEST_HPP__

#include<vector>
#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<time.h>
#include<semaphore.h>
#include<stdlib.h>



class RingQueue
{
private:
	std::vector<int> ring;
	int cap;
	sem_t blank_sem;
	sem_t data_sem;

	int c_step;										//consume在圈中的位置
	int p_step;		  								//product在圈中的位置
private:
	void P(sem_t &sem)
	{
		sem_wait(&sem);
	}
	void V(sem_t &sem)
	{
		sem_post(&sem);
	}
public:
	RingQueue(int cap_):cap(cap_),ring(cap_)
	{
		c_step=p_step=0;							//初始時c_step和p_step在同一格
		sem_init(&blank_sem,0,cap);				//初始時需要寫入的輸入是整個圈的容量
		sem_init(&data_sem,0,0);					//初始時需要consume的值為0
	}
	void PushData(const int& data)					//進行資料生產
	{
		P(blank_sem);
		ring[p_step]=data;							//把資料放進去
		V(data_sem);
		p_step++;
		p_step%=cap;								//進行模運算來模擬環形特性
	}
	void PopData(int &data  )
	{
		P(data_sem);								//申請資料資源
		data=ring[c_step];							//拿到資料
		V(blank_sem);								//空出格子
		c_step++;
		c_step%=cap;
	}
	~RingQueue()
	{
		sem_destroy(&blank_sem);
		sem_destroy(&data_sem);
	}

};

#endif
******   makefile   ******

ringqueue:ringqueue
	.cc
	g++ -o  [email protected] $^ -lpthread -fpermissive
.PHONY:clean
clean:
	rm -f ringqueue