基于环形队列的生产消费模型

Task.hpp:

#include<functional>
class Task{
public:
    using func_t=std::function<std::string(int,int,char)>;
    Task(){}
    Task(const func_t &fun,const int &x,const int &y,const char &op):\
    _fun(fun),_x(x),_y(y),_op(op){}
    ~Task(){}
    std::string operator()(){
        return _fun(_x,_y,_op);
    }
private:
    func_t _fun;
    int _x,_y;
    char _op;
};

RingQueue.hpp:

#include<semaphore.h>
#include<pthread.h>
#include<vector>
const int gcap=5;
template<class T>
class RingQueue{
public:
    RingQueue(const int &cap=gcap):_cap(cap){
        _q.resize(_cap);
        sem_init(&psem,0,_cap);
        sem_init(&csem,0,0);
        pthread_mutex_init(&pmutex,nullptr);
        pthread_mutex_init(&cmutex,nullptr);
        pid=cid=0;
    }
    ~RingQueue(){
        sem_destroy(&psem);
        sem_destroy(&csem);
        pthread_mutex_destroy(&pmutex);
        pthread_mutex_destroy(&cmutex);
    }
    void Push(const T& task){
        P(psem);
        pthread_mutex_lock(&pmutex);
        _q[pid++]=task;
        pid%=_cap;
        pthread_mutex_unlock(&pmutex);
        V(csem);
    }
    void Pop(T& task){
        P(csem);
        pthread_mutex_lock(&cmutex);
        task=_q[cid++];
        cid%=_cap;
        pthread_mutex_unlock(&cmutex);
        V(psem);
    }
private:
    void P(sem_t &sem){
        sem_wait(&sem);
    }
    void V(sem_t &sem){
        sem_post(&sem);
    }
    std::vector<T> _q;
    sem_t psem,csem;
    pthread_mutex_t pmutex,cmutex;
    int pid,cid;
    int _cap;
};

main.cpp:

#include "RingQueue.hpp"
#include "Task.hpp"
#include<iostream>
#include<unistd.h>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#define NUM 5
std::string op="+-*/%";
std::string calc(int x,int y,char op){
    int ret=0;
    switch(op){
        case '+':ret=x+y;
        break;
        case '-':ret=x-y;
        break;
        case '*':ret=x*y;
        break;
        case '/':{
            if(y==0){
                return "div zero wrong";
            }
            else{
                ret=x/y;
            }
            break;
        }
        case '%':{
            if(y==0){
                return "mod zero wrong";
            }
            else{
                ret=x%y;
            }
            break;
        }
    }
    char buffer[64];
    snprintf(buffer,sizeof buffer,"%d %c %d = %d",x,op,y,ret);
    return buffer;
}
std::string getSelfName(){
    char buffer[256];
    snprintf(buffer,sizeof buffer,"thread[0x%x]",pthread_self());
    return buffer;
}
void *comsumer(void * args){
    RingQueue<Task> *rq=static_cast<RingQueue<Task>*>(args);
    while(true){
        sleep(1);
        Task t;
        rq->Pop(t);
        std::cout<<getSelfName()<<" : "<<t()<<std::endl;
    }
}
void *productor(void *args){
    RingQueue<Task> *rq=static_cast<RingQueue<Task>*>(args);
    while(true){
        int x=rand()%10000;
        int y=rand()%10000;
        int idx=rand()%5;
        rq->Push(Task(calc,x,y,op[idx]));
        std::cout<<getSelfName()<<" : "<<x<<' '<<op[idx]<<' '<<y<<" = ?"<<std::endl;
    }
}
int main(){
    srand((unsigned int)time(nullptr)^getpid());
    RingQueue<Task> *rq=new RingQueue<Task>;
    pthread_t c[NUM],p[NUM];
    for(int i=0;i<NUM;i++){
        pthread_create(&c[i],nullptr,comsumer,rq);
    }
    for(int i=0;i<NUM;i++){
        pthread_create(&p[i],nullptr,productor,rq);
    }
    for(int i=0;i<NUM;i++){
        pthread_join(c[i],nullptr);
    }
    for(int i=0;i<NUM;i++){
        pthread_join(p[i],nullptr);
    }
    delete rq;
    return 0;
}
posted @ 2025-11-04 20:12  xdhking  阅读(6)  评论(0)    收藏  举报