一个线程读,另一个线程写的队列.
没有经过测试, 如果有什么bug,欢迎指正
#include
<
list
>
#include < Windows.h >
// gegerator a null handle
template < typename HandleType >
struct null_handle_generator
... {
static HandleType get()
...{
return static_cast<HandleType>(0);
}
} ;
/**/ /**
* 仅一个线程读一个线程写的list
*/
template < typename T, typename NullGenerator = null_handle_generator < T > >
class CSingleReadSingleWriteList
... {
std::list<T> m_list; /**////<存储T的双向链表
CRITICAL_SECTION m_cs; ///<对list的线程保护
HANDLE m_hEvent; ///<get()堵塞等待时等待的事件
bool m_bWaiting; ///<get()是否在堵塞等待
bool m_bInitSucc; ///<是否成功初始化
bool m_bCancelWait; ///<是否取消get()的堵塞
public:
CSingleReadSingleWriteList(void):
m_bWaiting( false ),
m_hEvent( NULL ),
m_bInitSucc( false ).
m_bCancelWait( false )
...{
}
virtual ~CSingleReadSingleWriteList(void)
...{
if( m_bInitSucc )
...{
SAFE_CLOSEHANDLE( m_hEvent );
DeleteCriticalSection( &m_cs );
}
}
/**//**
* 初始化使用队列必须的成员。
* 如果初始化失败,不能使用CSingleReadSingleWriteList,调用GetLastError()查具体原因
*/
bool init()
...{
if( ::InitializeCriticalSectionAndSpinCount( &m_cs, 0x80000400 ) )
...{
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_bInitSucc = true;
}
return m_bInitSucc;
}
/**//**
* 以堵塞的方式从队列中取一个元素
*/
T get()
...{
if( !m_bInitSucc ) return NULLGenerator::get();
EnterCriticalSection( &m_cs );
if( m_list.size() == 0 ) m_bWaiting = true;
LeaveCriticalSection( &m_cs );
if( m_bWaiting )
...{
if( m_hEvent )
...{
WaitForSingleObject( m_hEvent, INFINITE );
}
else
...{
while( m_list.size() == 0 && !m_bCancelWait )
...{
Sleep( 1 );
}
}
m_bWaiting = false;
}
EnterCriticalSection( &m_cs );
if( m_list.size() == 0 )
...{
LeaveCriticalSection( &m_cs );
//仅在不希望以后再调get了,队列将销毁时才可能进入这里,
//返回T的无效值,调用者在得到无效值时,以后不应该在调用这个实例的任何方法
return NULLGenerator::get();
}
T t = m_list.front();
m_list.pop_front();
if( m_hEvent && m_list.size() == 0 ) ResetEvent( m_hEvent );
LeaveCriticalSection( &m_cs );
return t;
}
/**//**
* 向队列填入一个元素
*/
void put( T t )
...{
//不允许填入无效的T值到队列
if( !m_bInitSucc || t == NULLGenerator::get() ) return;
EnterCriticalSection( &m_cs );
m_list.push_back( t );
if( m_bWaiting && m_hEvent && m_list.size()==1 )
...{
SetEvent( m_hEvent );
}
LeaveCriticalSection( &m_cs );
}
/**//**
* 如果get堵塞,需要调用取消堵塞。比如在需要使get线程退出,但get被堵住时
*/
void cancelGet()
...{
if( !m_bInitSucc ) return;
EnterCriticalSection( &m_cs );
if( m_bWaiting && m_hEvent && m_list.size()==0 )
...{
SetEvent( m_hEvent );
}
m_bCancelWait = true;
LeaveCriticalSection( &m_cs );
}
} ;
#include < Windows.h >
// gegerator a null handle
template < typename HandleType >
struct null_handle_generator
... {
static HandleType get()
...{
return static_cast<HandleType>(0);
}
} ;
/**/ /**
* 仅一个线程读一个线程写的list
*/
template < typename T, typename NullGenerator = null_handle_generator < T > >
class CSingleReadSingleWriteList
... {
std::list<T> m_list; /**////<存储T的双向链表
CRITICAL_SECTION m_cs; ///<对list的线程保护
HANDLE m_hEvent; ///<get()堵塞等待时等待的事件
bool m_bWaiting; ///<get()是否在堵塞等待
bool m_bInitSucc; ///<是否成功初始化
bool m_bCancelWait; ///<是否取消get()的堵塞
public:
CSingleReadSingleWriteList(void):
m_bWaiting( false ),
m_hEvent( NULL ),
m_bInitSucc( false ).
m_bCancelWait( false )
...{
}
virtual ~CSingleReadSingleWriteList(void)
...{
if( m_bInitSucc )
...{
SAFE_CLOSEHANDLE( m_hEvent );
DeleteCriticalSection( &m_cs );
}
}
/**//**
* 初始化使用队列必须的成员。
* 如果初始化失败,不能使用CSingleReadSingleWriteList,调用GetLastError()查具体原因
*/
bool init()
...{
if( ::InitializeCriticalSectionAndSpinCount( &m_cs, 0x80000400 ) )
...{
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
m_bInitSucc = true;
}
return m_bInitSucc;
}
/**//**
* 以堵塞的方式从队列中取一个元素
*/
T get()
...{
if( !m_bInitSucc ) return NULLGenerator::get();
EnterCriticalSection( &m_cs );
if( m_list.size() == 0 ) m_bWaiting = true;
LeaveCriticalSection( &m_cs );
if( m_bWaiting )
...{
if( m_hEvent )
...{
WaitForSingleObject( m_hEvent, INFINITE );
}
else
...{
while( m_list.size() == 0 && !m_bCancelWait )
...{
Sleep( 1 );
}
}
m_bWaiting = false;
}
EnterCriticalSection( &m_cs );
if( m_list.size() == 0 )
...{
LeaveCriticalSection( &m_cs );
//仅在不希望以后再调get了,队列将销毁时才可能进入这里,
//返回T的无效值,调用者在得到无效值时,以后不应该在调用这个实例的任何方法
return NULLGenerator::get();
}
T t = m_list.front();
m_list.pop_front();
if( m_hEvent && m_list.size() == 0 ) ResetEvent( m_hEvent );
LeaveCriticalSection( &m_cs );
return t;
}
/**//**
* 向队列填入一个元素
*/
void put( T t )
...{
//不允许填入无效的T值到队列
if( !m_bInitSucc || t == NULLGenerator::get() ) return;
EnterCriticalSection( &m_cs );
m_list.push_back( t );
if( m_bWaiting && m_hEvent && m_list.size()==1 )
...{
SetEvent( m_hEvent );
}
LeaveCriticalSection( &m_cs );
}
/**//**
* 如果get堵塞,需要调用取消堵塞。比如在需要使get线程退出,但get被堵住时
*/
void cancelGet()
...{
if( !m_bInitSucc ) return;
EnterCriticalSection( &m_cs );
if( m_bWaiting && m_hEvent && m_list.size()==0 )
...{
SetEvent( m_hEvent );
}
m_bCancelWait = true;
LeaveCriticalSection( &m_cs );
}
} ;