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;
}