#include <boost/thread.hpp>
class rwMutex
{
private:
boost::mutex lockMutex; // 同步控制互斥变量,控制对标志量得访问
boost::condition_variable_any condWriter; // 写者条件变量
boost::condition_variable_any condReader; // 读者条件变量
unsigned long waitWriter; // 记录写者等待数
unsigned long waitReader; // 记录读者等待数
// 进入缓冲区标志,holder = -1,读者在缓冲区; holder = 0,均不在缓冲区; holder > 0,有多个读者在缓冲区
long holder;
const bool priority; // priority = true,写者优先; false 读者优先,默认是写者优先
private:
rwMutex& operator= ( const rwMutex&);
rwMutex(const rwMutex&);
public:
rwMutex( const bool flag = true );
void rdlock(); // 读者占锁
void wrlock(); // 写者占锁
void unrdlock(); // 读者释放锁
void unwrlock(); // 写者释放锁
};
rwMutex::rwMutex( const bool flag )
:waitWriter(0),
waitReader(0),
holder(0),
priority(flag)
{}
void rwMutex::rdlock()
{
boost::mutex::scoped_lock innerLock(lockMutex);
// 有写者存在,则直接阻塞
while(holder < 0)
{
++waitReader;
condReader.wait(lockMutex);
--waitReader;
}
// 没有人占有资源
if(0 == holder)
{
if(priority)
{
while(waitWriter >0)
{
++waitReader;
condReader.wait(lockMutex);
--waitReader;
}
}
}
// 读者占有资源,直接进入
++holder;
}
void rwMutex::wrlock()
{
boost::mutex::scoped_lock innerLock(lockMutex);
// 有读者或者是写者占有资源
while (0 != holder)
{
++waitWriter;
condWriter.wait(lockMutex);
--waitWriter;
}
// 没有人占有资源,但是可能有等待者
if(!priority)
{
while(waitReader >0)
{
++waitWriter;
condWriter.wait(lockMutex);
--waitWriter;
}
}
holder = -1;
}
void rwMutex::unrdlock()
{
{
boost::mutex::scoped_lock innerLock(lockMutex);
--holder;
}
// 写者一定是阻塞的,直到hodler=0的时候才会通知写着,所以无论是哪个读者线程发出通知都不要紧
if (0 == holder && waitWriter >0)
condWriter.notify_one();
}
void rwMutex::unwrlock()
{
{
boost::mutex::scoped_lock innerLock(lockMutex);
holder = 0;
}
// 之所以放在锁的外面是因为:如果有写者操作,那么读者和写者必定会全部阻塞,那么要唤醒一个等待的子线程
// 就需要我们显示通知,所以可以放在外面,同时避免了通知后因为没有释放锁,读者或者写者需要等待
// 读者退出,如果写者优先
if (priority)
{
if (waitWriter >0)
condWriter.notify_one();
else if (waitReader >0)
condReader.notify_all(); // 因为读者可以并入
}
else
{
// 如果是读者优先
if (waitReader >0)
condReader.notify_all();
else if (waitWriter >0)
condWriter.notify_one();
}
}
class readerLock
{
private:
rwMutex &mutex;
public:
readerLock(rwMutex &m)
:mutex(m)
{
mutex.rdlock();
}
~readerLock()
{
mutex.unrdlock();
}
};
class writerLock
{
private:
rwMutex &mutex;
public:
writerLock(rwMutex &m)
:mutex(m)
{
mutex.wrlock();
}
~writerLock()
{
mutex.unwrlock();
}
};
rwMutex myMutex;
boost::mutex iomutex;
void reader()
{
readerLock lock(myMutex);
boost::mutex::scoped_lock iolock(iomutex);
std::cout << "reader inside buffer,my thread id = " << boost::this_thread::get_id() << "\n";
}
void writer()
{
writerLock lock(myMutex);
std::cout << "writer inside buffer,my thread id = " << boost::this_thread::get_id() << "\n";
}
int main( int argc, char *argv )
{
boost::thread_group gr;
gr.create_thread(writer);
gr.create_thread(writer);
gr.create_thread(writer);
gr.create_thread(reader);
gr.create_thread(reader);
gr.create_thread(reader);
gr.create_thread(writer);
gr.create_thread(writer);
gr.create_thread(writer);
gr.create_thread(reader);
gr.create_thread(reader);
gr.create_thread(reader);
gr.create_thread(writer);
gr.create_thread(writer);
gr.create_thread(writer);
gr.join_all();
return 0;
};