// BlockingQueue.h: interface for the CBlockingQueue class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_)
#define AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <windows.h>
#include <LIST>
#include <vector>
#include <STRING>
using namespace std;
class CBlockingQueue
{
public:
CBlockingQueue(int size);
virtual ~CBlockingQueue();
private:
CBlockingQueue();
HANDLE m_MssageNullEvent;
HANDLE m_synSignal;
int m_size;
list<string> m_msgs;
public:
string Dequeue();
void Enqueue(string msg);
};
#endif // !defined(AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_)
// BlockingQueue.cpp: implementation of the CBlockingQueue class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BlockingQueue.h"
#include <afxcom_.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBlockingQueue::CBlockingQueue()
{
}
CBlockingQueue::CBlockingQueue(int ssize)
{
m_size=ssize;
m_synSignal=CreateSemaphore(NULL,1,1,"m_synSignal");
m_MssageNullEvent=CreateEvent(NULL,TRUE,TRUE,"m_MssageNullEvent");
}
CBlockingQueue::~CBlockingQueue()
{
}
string CBlockingQueue::Dequeue()
{
string msg="";
WaitForSingleObject(m_synSignal,INFINITE);
while(0==m_msgs.size())
{
bool breset=ResetEvent(m_MssageNullEvent);
ReleaseSemaphore(m_synSignal,1,NULL);
DWORD nret=WaitForSingleObject(m_MssageNullEvent,INFINITE);
//ASSERT(WAIT_TIMEOUT!=);
}
string temp=*m_msgs.begin();
m_msgs.pop_front();
SetEvent(m_MssageNullEvent);
ReleaseSemaphore(m_synSignal,1,NULL);
return temp;
}
void CBlockingQueue::Enqueue(string msg)
{
WaitForSingleObject(m_synSignal,INFINITE);
int a=m_msgs.size();
while(m_size==m_msgs.size())
{
bool bret= ResetEvent(m_MssageNullEvent);
ReleaseSemaphore(m_synSignal,1,NULL);
DWORD nret= WaitForSingleObject(m_MssageNullEvent,INFINITE);
}
m_msgs.push_back(msg);
ReleaseSemaphore(m_synSignal,1,NULL);
if (1==m_msgs.size())
SetEvent(m_MssageNullEvent);
}
以上不具有普遍性,更合理的设计如下:
将 同步内核对象抽象出来 成为 CMonitor
// Monitor.h: interface for the CMonitor class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MONITOR_H__26A4800D_6F3C_41BF_97AC_1D20860517AC__INCLUDED_)
#define AFX_MONITOR_H__26A4800D_6F3C_41BF_97AC_1D20860517AC__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <windows.h>
class CMonitor
{
public:
CMonitor();
virtual ~CMonitor();
private:
HANDLE m_h[2];
DWORD m_lastThreadId;
public:
void wait(DWORD timeout);
bool pulse();
void Enter();
void Exit();
};
#endif // !defined(AFX_MONITOR_H__26A4800D_6F3C_41BF_97AC_1D20860517AC__INCLUDED_)
// Monitor.cpp: implementation of the CMonitor class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Monitor.h"
#include <exception>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMonitor::CMonitor()
{
m_h[0]=CreateEvent(NULL,TRUE,TRUE,"h1");
m_h[1]=CreateEvent(NULL,TRUE,TRUE,"h2");
m_lastThreadId=0;
}
CMonitor::~CMonitor()
{
}
void CMonitor::Enter()
{
m_lastThreadId=::GetCurrentThreadId();
WaitForSingleObject(m_h[0],INFINITE);//ResetEvent();
}
void CMonitor::Exit()
{
m_lastThreadId=NULL;
SetEvent(m_h[0]);
SetEvent(m_h[1]);
}
bool CMonitor::pulse()
{
if (!(m_lastThreadId!=NULL || m_lastThreadId!=::GetCurrentThreadId()))
{
throw exception("The wait could only be excuted by the monitor owner!");
}
SetEvent(m_h[1]);
return true;
}
void CMonitor::wait( DWORD timeout )
{
if (!(m_lastThreadId!=NULL || m_lastThreadId!=::GetCurrentThreadId()))
{
throw exception("The wait could only be excuted by the monitor owner!");
}
m_lastThreadId=NULL;
ResetEvent(m_h[1]);
WaitForSingleObject(m_h[1],timeout);
SetEvent(m_h[0]);
}
那么新的 BlockingQueue代码如下:
// BlockingQueue.h: interface for the CBlockingQueue class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_)
#define AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <windows.h>
#include <LIST>
#include <vector>
#include <STRING>
#include "Monitor.h"
using namespace std;
class CBlockingQueue
{
public:
CBlockingQueue(int size);
virtual ~CBlockingQueue();
private:
CBlockingQueue();
int m_size;
list<string> m_msgs;
CMonitor m_monitor;
public:
string Dequeue();
void Enqueue(string msg);
};
#endif // !defined(AFX_BLOCKINGQUEUE_H__E6C614E8_4A5D_4D18_A38D_845018DA75B6__INCLUDED_)
// BlockingQueue.cpp: implementation of the CBlockingQueue class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BlockingQueue.h"
#include <afxcom_.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBlockingQueue::CBlockingQueue()
{
}
CBlockingQueue::CBlockingQueue(int ssize)
{
m_size=ssize;
}
CBlockingQueue::~CBlockingQueue()
{
}
string CBlockingQueue::Dequeue()
{
string msg="";
m_monitor.Enter();
{
while(0==m_msgs.size())
{
m_monitor.wait(INFINITE);
}
msg=*m_msgs.begin();
m_msgs.pop_front();
if ((m_size-1)==m_msgs.size())
m_monitor.pulse();
}
m_monitor.Exit();
return msg;
}
void CBlockingQueue::Enqueue(string msg)
{
m_monitor.Enter();
{
int a=m_msgs.size();
while(m_size==m_msgs.size())
{
m_monitor.wait(INFINITE);
}
m_msgs.push_back(msg);
if (1==m_msgs.size())
m_monitor.pulse();
}
m_monitor.Exit();
}