参考自
https://wenku.baidu.com/view/ff323be3b5daa58da0116c175f0e7cd18425188c.html
#include<iostream>
#include<string>
#include<cstdlib>
#include <queue>
#include<algorithm>
#include<stdio.h>
#include<malloc.h>
#include<string.h>
using namespace std;
//pcb结构
struct PCB{
char name[10];//进程名
int id;//进程标号 1为生产者,2为消费者
};
//链队列
typedef struct QNode{
PCB data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;//头指针
QueuePtr rear;//尾指针
}LinkQueue;
//初始化链队列
void QueueInit(LinkQueue &Q){
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
Q.front->next=NULL;
}
//入队
void EnQueue(LinkQueue &Q,QueuePtr p){
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
}
//出队,返回的是QueuePtr类型的元素。
QueuePtr DeQueue(LinkQueue &Q){
QueuePtr p=Q.front->next;
Q.front->next=p->next;
if(Q.rear==p){
Q.rear=Q.front;
}
return p;
}
//出队
/*
void outqueue(LinkQueue &Q){
QueuePtr p=Q.front->next;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
delete p;
}
*/
//创建进程进入初始队列
void processproc(LinkQueue &Q){
int processNum=0;
cout<<"请输入进程个数:";
cin>>processNum;
for(int i=0;i<processNum;i++){
cout<<"输入第"<<i+1<<"个进程的种类,生产者输入1,消费者输入2"<<endl;
struct PCB pcb;
cin>>pcb.id;
cout<<"输入进程名";
cin>>pcb.name;
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
p->data.id=pcb.id;
strcpy(p->data.name,pcb.name);
EnQueue(Q,p);
}
}
//判断队列是否为空
bool HasElement(LinkQueue Q){
if(Q.front==Q.rear)
return 0;
else
return 1;
}
//生产者
int ProduceRun(int &full,int BufferSize){
if(full<BufferSize){//即还有空间
full++;
return 1;
}
return 0;
}
//消费者
int ConsumeRun(int &full,int BufferSize){
if(full>0){
full--;
return 1;
}
return 0;
}
//打印队列
void DisPlay(LinkQueue Q){
QueuePtr p=Q.front;
while(p->next){
cout<<"进程"<<p->next->data.name<<endl;
p=p->next;
}
}
//打印over队列
void DisPlay1(LinkQueue Q){
QueuePtr p=Q.front;
while(p->next){
cout<<p->next->data.id<<" ";
p=p->next;
}
cout<<endl;
}
//队列元素个数
int queuenum(LinkQueue Q){
int count=0;
QueuePtr p;
p=Q.front->next;
while(p!=NULL){
count++;
p=p->next;
}
return count;
}
int main(){
int BufferSize;//缓冲区大小
cout<<"设置缓冲区大小:";
cin>>BufferSize;
int full=0;//当前缓冲区中进程数目
int temp=1;
LinkQueue over;//结束链表
QueueInit(over);//链表初始化
LinkQueue ReadyQueue;//就绪队列
LinkQueue ProducerWaitQueue;//生产者等待队列
LinkQueue ConsumerWaitQueue;//消费者等待队列
QueueInit(ReadyQueue);
QueueInit(ProducerWaitQueue);
QueueInit(ConsumerWaitQueue);
processproc(ReadyQueue);//进程初始化
bool element=queuenum(ReadyQueue);//判断就绪队列是否为空
while(element){
cout<<"进程"<<ReadyQueue.front->next->data.name<<"申请运行,它是一个";
if(ReadyQueue.front->next->data.id==1){//生产者进程
cout<<"生产者"<<endl;
if(ProduceRun(full,BufferSize)==1){//即还有空间可存入
cout<<"进程"<<ReadyQueue.front->next->data.name<<"执行完毕"<<endl;
EnQueue(over,DeQueue(ReadyQueue));
//outqueue(ReadyQueue);
if(queuenum(ConsumerWaitQueue)!=0){//消费者等待队列仍有消费者时候。要唤醒消费者
EnQueue(ReadyQueue,DeQueue(ConsumerWaitQueue));
//outqueue(ConsumerWaitQueue);
}
}
else if(ProduceRun(full,BufferSize)==0){//如果没空间,则进入生产者等待队列
EnQueue(ProducerWaitQueue,DeQueue(ReadyQueue));
//outqueue(ReadyQueue);
if(queuenum(ConsumerWaitQueue)!=0){//消费者等待队列中有,则入到就绪队列,即唤醒消费者。
EnQueue(ReadyQueue,DeQueue(ConsumerWaitQueue));
//outqueue(ConsumerWaitQueue);
}
}
}
else{//消费者
cout<<"消费者"<<endl;
if(ConsumeRun(full,BufferSize)==1){//即buffer中有生产者进程。full-1,消费掉一个生产者,并进入over链表
EnQueue(over,DeQueue(ReadyQueue));
//outqueue(ReadyQueue);
}
else if(ConsumeRun(full,BufferSize)==0){//buffer中无进程,进入消费者等待,同时唤醒生产者
EnQueue(ConsumerWaitQueue,DeQueue(ReadyQueue));//加入消费者等待
if(queuenum(ProducerWaitQueue)!=0){//生产者等待队列中有数据,则加入到就绪队列,即唤醒生产者。
EnQueue(ReadyQueue,DeQueue(ProducerWaitQueue));
cout<<"生产者等待队列数量"<<queuenum(ProducerWaitQueue)<<endl;
//outqueue(ProducerWaitQueue);
}
}
}
//输出就绪队列
element=HasElement(ReadyQueue);
if(HasElement(ReadyQueue)){
cout<<"就绪队列中有以下进程:"<<endl;
DisPlay(ReadyQueue);
}
else
cout<<"就绪队列中没有进程"<<endl;
//输出生产者等待队列
if(queuenum(ProducerWaitQueue)!=0){
cout<<"生产者等待队列中有以下进程:"<<endl;
DisPlay(ProducerWaitQueue);
}
else
cout<<"生产者等待队列中没有进程"<<endl;
//输出消费者等待队列
if(queuenum(ConsumerWaitQueue)!=0){
cout<<"消费者等待队列中有以下进程:"<<endl;
DisPlay(ConsumerWaitQueue);
}
else
cout<<"消费者等待队列中没有进程"<<endl;
cout<<endl;
}
cout<<"最终over队列中生产者消费者id为"<<endl;
DisPlay1(over);
return 0;
}