#include<pthread.h>
#include<string>
#include<unistd.h>
#include<fstream>
#include<iostream>
using namespace std;
class Mutex
{
public:
Mutex()
{
pthread_mutex_init(&mutex_,NULL);
}
~Mutex()
{
pthread_mutex_destroy(&mutex_);
}
void lock()
{
pthread_mutex_lock(&mutex_);
}
void unlock()
{
pthread_mutex_unlock(&mutex_);
}
pthread_mutex_t* getPthreadMutex()
{
return &mutex_;//绝对不能返回copy
}
private:
pthread_mutex_t mutex_;
};
class ScopeMutex
{
public:
ScopeMutex(Mutex &mutex):mutexLock(mutex)
{
mutexLock.lock();
}
~ScopeMutex()
{
mutexLock.unlock();
}
private:
Mutex & mutexLock;
};
class Condition
{
public:
Condition(Mutex& m):mutex_(m)
{
pthread_cond_init(&cond_,NULL);
}
~Condition()
{
pthread_cond_destroy(&cond_);
}
void notify()
{
pthread_cond_signal(&cond_);
}
void wait()
{
pthread_cond_wait(&cond_,mutex_.getPthreadMutex());
}
private:
Mutex mutex_;
pthread_cond_t cond_;
};
Mutex smutex_[4];
Mutex mutex_[4];
Condition cond_[] = {
mutex_[0],
mutex_[1],
mutex_[2],
mutex_[3],
};
ofstream ofile[4];
int myNextFileIndex[4] = {3,2,1,0};
void *ThreadWriter(void* pNum);
int main(int argc, char const *argv[])
{
string filename("A");
for (int i = 0; i < 4; ++i)
{
filename[0]+=i;
ofile[i].open(filename.data(), ios::out|ios::binary);
if (ofile[i].fail())
{
cout << "fail to open" << endl;
return -1;
}
}
pthread_t tid[4];
for (int i = 0; i < 4; ++i)
{
cout << "pthread_creating :" << i << endl;
pthread_create(&tid[i], NULL, ThreadWriter, &i);
sleep(1);
}
sleep(2);
cout << "try to notify thread 1 "<<endl;
cond_[0].notify();
for (int i = 0; i < 4; ++i)
{
pthread_join(tid[i],NULL);
}
for (int i = 0; i < 4; ++i)
{
ofile[i].close();
}
return 0;
}
void *ThreadWriter(void* pNum)
{
int threadId = (int)(*((int*)pNum));
while(1)
{
cond_[threadId].wait();// 等别人通知我
ScopeMutex scope(smutex_[threadId]);// lockup
cout << "thread " << threadId << " is writing " << myNextFileIndex[threadId];
ofile[myNextFileIndex[threadId]] << threadId+1;// 写文件
int tmp = myNextFileIndex[threadId];
myNextFileIndex[threadId] = (tmp == 0) ?3:--tmp; // 更新我下次要写的fileId
cout << " myNextFileIndex is "<< myNextFileIndex[threadId] << endl;
sleep(1);
cond_[(threadId+1) %4].notify();// 0 ->1 1->2
}
}