// Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <process.h> #include <queue> using namespace std; class CMessage { public: OVERLAPPED m_ov; }; template<class T> class IMessageQueue { public: IMessageQueue(){} virtual ~IMessageQueue(){} virtual bool PushMsg( const T & item ) = 0 ; virtual bool TakeMsg( T &item ) = 0 ; virtual ULONG GetMsgAmount() const = 0 ; }; template<class T> class CIOCPQueue : public IMessageQueue<T> { public: CIOCPQueue():m_nMsgAmount(0),completion_port_(0) { T item; completion_port_ = ::CreateIoCompletionPort( INVALID_HANDLE_VALUE , NULL , (ULONG_PTR)(&item) , NULL ); } virtual ~CIOCPQueue() { //remove msg , clear T item ; while ( this->TakeMsg( item ) ) { } ::CancelIo( completion_port_ ); ::CloseHandle( completion_port_ ); completion_port_ = 0; } virtual bool PushMsg( const T & item ) { DWORD dwBytesTransferred = 0 ; ULONG_PTR dwCompletionKey = 0 ; BOOL bRet = ::PostQueuedCompletionStatus( completion_port_ , dwBytesTransferred , (ULONG_PTR)item , &(item->m_ov) ); if ( bRet ) { ::InterlockedIncrement( &m_nMsgAmount ); return true; } return false; } virtual bool TakeMsg( T &item ) { if ( m_nMsgAmount<=0 ) { return false; } DWORD dwBytesTransferred = 0 ; ULONG_PTR dwCompletionKey = 0 ; LPOVERLAPPED overlapped = 0 ; static const unsigned int unTimeout = 1; //only 1 millsecond timeout BOOL bRet = ::GetQueuedCompletionStatus( completion_port_ , &dwBytesTransferred , &dwCompletionKey , &overlapped , unTimeout ); if ( bRet && dwCompletionKey!=NULL ) { ::InterlockedDecrement( &m_nMsgAmount ); item = (T )( dwCompletionKey ); return true; } return false; } virtual ULONG GetMsgAmount() const { return m_nMsgAmount; } private: HANDLE completion_port_; volatile long m_nMsgAmount; }; template<class T> class CSafeQueue : public IMessageQueue<T> { public: CSafeQueue():m_nMsgAmount(0) { InitializeCriticalSection(&m_csLock); } virtual ~CSafeQueue() { ::DeleteCriticalSection(&m_csLock); } virtual bool PushMsg( const T & item ) { ::EnterCriticalSection( &m_csLock ); m_Queue.push( item ); ::InterlockedIncrement( &m_nMsgAmount ); ::LeaveCriticalSection( &m_csLock ); return true; } virtual bool TakeMsg( T &item ) { if ( m_nMsgAmount<=0 ) { return false; } ::EnterCriticalSection( &m_csLock ); item = m_Queue.back(); m_Queue.pop(); ::InterlockedDecrement( &m_nMsgAmount ); ::LeaveCriticalSection( &m_csLock ); return true; } virtual ULONG GetMsgAmount() const { return m_nMsgAmount; } private: volatile long m_nMsgAmount; queue<T> m_Queue; CRITICAL_SECTION m_csLock; }; void test1(); void test2(); int _tmain(int argc, _TCHAR* argv[]) { test1(); test2(); system("pause"); return 0; } void test1() { printf("**************test1**************/r/n" ); CIOCPQueue<CMessage *> Queue; CMessage *pMsg = new CMessage; printf("new msg=%p/r/n", pMsg ); bool bRet = Queue.PushMsg( pMsg ) ; printf("PushMsg msg=%s/r/n", bRet ? "true" :"false" ); //CMessage *pMessage = 0; //bRet=false; //bRet=Queue.TakeMsg( pMessage ); //printf("TakeMsg msg=%s,pMsg=%p/r/n", bRet ? "true" :"false",pMessage ); } void test2() { printf("**************test2**************/r/n" ); CSafeQueue<CMessage *> Queue; CMessage *pMsg = new CMessage; printf("new msg=%p/r/n", pMsg ); bool bRet = Queue.PushMsg( pMsg ) ; printf("PushMsg msg=%s/r/n", bRet ? "true" :"false" ); CMessage *pMessage = 0; bRet=false; bRet=Queue.TakeMsg( pMessage ); printf("TakeMsg msg=%s,pMsg=%p/r/n", bRet ? "true" :"false",pMessage ); }