/**
* @Author: yangrenyong AT gmail D#OT com
* @Date: 2011-7-14
*/
#include<iostream>
#include<vector>
#include<boost/utility.hpp>
#include<boost/thread/condition.hpp>
#include<boost/thread/thread.hpp>
typedef boost::mutex::scoped_lock Lock;
typedef boost::mutex Mutex;
typedef boost::condition Condition;
#define DEFINE_ENUM_MACRO(ENUMNAME,ENUMS...)\
struct ENUMNAME\
{\
enum __Enum\
{\
ENUMS\
};\
__Enum _val;\
explicit ENUMNAME(const int val = 0) :\
_val(__Enum(val))\
{\
\
}\
ENUMNAME& operator=(const int val)\
{\
\
_val = (__Enum ) val;\
\
return *this;\
}\
operator int() const\
{\
\
return _val;\
}\
};
DEFINE_ENUM_MACRO(BBState,Empty=0x01,Allocated=0x02,Filled=0x03)
struct ChunkType
{
ChunkType() :
Value(0), State(BBState::Empty)
{
}
int Value;
BBState State;
};
class BoundedBuffer: private boost::noncopyable
{
public:
BoundedBuffer(int n) :
m_vecCircularBuff(n), m_allocatableBuffer(n), m_filledBuffer(0),
m_sendThread(0)
{
}
// Send a value to an empty buffer and notify all threads waiting for data.
void Send()
{
++m_sendThread;
int c = 1000;
int validIndexToAllocate;
boost::xtime xt;
for (int i = 0; i < c; ++i)
{
bool found = false;
while (true)
{
Lock lk(m_allocatableBufferMutex);
if (m_allocatableBuffer == 0)
{
m_allocatableBufferCondition.wait(lk);
}
// Get the first buffer found not filled.
else
{
for (size_t i = 0; i < m_vecCircularBuff.size(); ++i)
{
if (m_vecCircularBuff[i].State == BBState::Empty)
{
validIndexToAllocate = i;
// Take the seat before real write.
m_vecCircularBuff[validIndexToAllocate].State
= BBState::Allocated;
--m_allocatableBuffer;
found = true;
break;
}
}
if (found)
{
break; // One data has succeeded in taking a seat.
}
}
}
// Have some sleep here.
boost::xtime_get(&xt, boost::TIME_UTC);
xt.nsec += int_fast32_t((rand() % 10) / 10.0 * 1e08); // Sleep 0~1.0s.
boost::thread::sleep(xt);
// Real write here.
m_vecCircularBuff[validIndexToAllocate].Value = sendBeg++;
m_vecCircularBuff[validIndexToAllocate].State = BBState::Filled;
{
Lock lk(m_ioMutex);
std::cout << "send thread: " << boost::this_thread::get_id()
<< ", sent: " << sendBeg - 1 << std::endl;
}
{
Lock lk(m_filledBufferMutex);
if (++m_filledBuffer == 1)
{
m_filledBufferCondition.notify_one();
}
}
}
{
Lock lk(m_sendThreadMutex);
--m_sendThread;
if (m_sendThread > 0)
{
m_allocatableBufferCondition.notify_all();
}
}
m_filledBufferCondition.notify_all();
}
void Receive()
{
int recvVal;
size_t indexToRead;
boost::xtime xt;
while (true)
{
Lock lk(m_filledBufferMutex);
if (m_filledBuffer > 0)
{
for (size_t i = 0; i < m_vecCircularBuff.size(); ++i)
{
if (m_vecCircularBuff[i].State == BBState::Filled)
{
// Take the seat first before real read.
indexToRead = i;
--m_filledBuffer;
break;
}
}
// Have some sleep here.
boost::xtime_get(&xt, boost::TIME_UTC);
xt.nsec += int_fast32_t((rand() % 10) / 20.0 * 1e08); // Sleep 0~1.0s.
boost::thread::sleep(xt);
recvVal = m_vecCircularBuff[indexToRead].Value;
m_vecCircularBuff[indexToRead].State = BBState::Empty;
{
Lock lk(m_allocatableBufferMutex);
if (++m_allocatableBuffer == 1)
{
m_allocatableBufferCondition.notify_one();
}
}
{
Lock lk(m_ioMutex);
std::cout << "receive thread: "
<< boost::this_thread::get_id() << ", receive: "
<< recvVal << std::endl;
}
}
else if (m_filledBuffer == 0 && m_sendThread > 0)
{
m_filledBufferCondition.wait(lk);
}
else
{
break;// Break to exit when all received.
}
}
}
private:
std::vector<ChunkType> m_vecCircularBuff;
size_t m_allocatableBuffer, m_filledBuffer, m_sendThread;
Mutex m_filledBufferMutex, m_allocatableBufferMutex, m_ioMutex,
m_sendThreadMutex;
Condition m_allocatableBufferCondition, m_filledBufferCondition,
m_sendThreadCondition;
static int sendBeg;
};
int BoundedBuffer::sendBeg = 1;
BoundedBuffer buf(2);
void sender()
{
buf.Send();
}
void receiver()
{
buf.Receive();
}
int main(int, char*[])
{
boost::thread_group senders;
boost::thread_group recvers;
for (int i = 0; i < 150; ++i)
{
senders.create_thread(&sender);
}
for (int i = 0; i < 150; ++i)
{
recvers.create_thread(&receiver);
}
senders.join_all();
recvers.join_all();
return 0;
}
多生产者,多消费者,延迟读写,有限环形缓冲区
最新推荐文章于 2020-07-15 12:00:03 发布