#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
//#define DEBUG
#define VOLATILE volatile
#ifndef VOLATILE
#define VOLATILE
#endif
#define handle_func_ret_val_ne0(func)\
do{if(func!=0) { perror(#func); exit(-1);} } while(0)
class locker
{
public:
locker ( pthread_mutex_t *mutex):lock(mutex){
pthread_mutex_lock(lock);
#ifdef DEBUG
cout<<"have locked!"<<endl;
#endif
}
~locker () {
pthread_mutex_unlock(lock);
#ifdef DEBUG
cout<<"have unlocked!"<<endl;
#endif
}
private:
pthread_mutex_t* lock;
};
class factory
{
public:
factory()
:push_pos(0),pop_pos(0),size(0){}
~factory(){
}
int pop(){
int ret=buffer[pop_pos++];
if(pop_pos==buffer_size)
pop_pos=0;
--size;
#ifdef DEBUG
cout<<"size: "<<size<<'\t';
#endif
return ret;
}
int push(int val){
buffer[push_pos++]=val;
if(push_pos==buffer_size)
push_pos=0;
++size;
#ifdef DEBUG
cout<<"size: "<<size<<'\t';
#endif
return val;
}
bool is_full(){
return size==buffer_size;
}
bool is_empty(){
return size==0;
}
protected:
VOLATILE int push_pos;
VOLATILE int pop_pos;
VOLATILE int size;
static const int buffer_size=5;
private:
int buffer[buffer_size];
};
class factory_manager
{
public:
factory_manager():
mutex(PTHREAD_MUTEX_INITIALIZER),
not_empty(PTHREAD_COND_INITIALIZER),
not_full(PTHREAD_COND_INITIALIZER){}
~factory_manager(){
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(¬_empty);
pthread_cond_destroy(¬_full);
}
int put(int val){
{
locker lock(&mutex);
while(ft.is_full()){
#ifdef DEBUG
cout<<"in put method:factory is full!"<<endl;
#endif
pthread_cond_wait(¬_full,&mutex);
#ifdef DEBUG
cout<<"in put method:someone wakes me up!"<<endl;
#endif
}
ft.push(val);
}
pthread_cond_signal(¬_empty);
return val;
}
int get(){
int val;
{
locker lock(&mutex);
while(ft.is_empty()){
#ifdef DEBUG
cout<<"in get method:factory is empty!"<<endl;
#endif
pthread_cond_wait(¬_empty,&mutex);
#ifdef DEBUG
cout<<"in get method:someone wakes me up!"<<endl;
#endif
}
val=ft.pop();
}
pthread_cond_signal(¬_full);
return val;
}
private:
pthread_mutex_t mutex;
pthread_cond_t not_empty;
pthread_cond_t not_full;
factory ft;
};
class user
{
public:
user(const string& n,factory_manager& f):name(n),fm(f){}
~user(){}
virtual void run()=0;
protected:
string name;
factory_manager& fm;
};
class producer:public user
{
public:
producer(const string& n,factory_manager& f):user(n,f){}
~producer(){}
void run(){
#ifdef DEBUG
cout<<name<<" start runing!"<<endl;
#endif
srand(time(0));
for(int i=0;i<10;++i){
int val=rand();
fm.put(val);
cout<<name<<" produced "<<val<<endl;
}
}
};
class customer:public user
{
public:
customer(const string& n,factory_manager& f):user(n,f){}
~customer(){}
void run(){
#ifdef DEBUG
cout<<name<<" start runing!"<<endl;
#endif
for(int i=0;i<10;++i){
int val=fm.get();
cout<<name<<" get "<<val<<endl;
sleep(1);
}
}
};
void* thread_func(void* data)
{
user* u=(user*)data;
u->run();
}
int main()
{
factory_manager manager;
producer pa("producera",manager);
producer pb("producerb",manager);
customer ca("customera",manager);
customer cb("customerb",manager);
user* user_table[4]={&pa,&pb,&ca,&cb};
pthread_t thread_table[4];
for(int i=0;i<4;++i){
pthread_create(&thread_table[i],0,thread_func,user_table[i]);
}
for(int i=0;i<4;++i){
pthread_join(thread_table[i],0);
}
cout<<"done!"<<endl;
}
转载于:https://my.oschina.net/u/1022744/blog/156198