BufferCounter complex access control class. This is a thread-safe counter, which signals the consumer on not empty (the producer has just inserted a message into a previously empty buffer) and the producer on not full (the consumer has just removed a message from the previously full buffer). class CriticalSection : public CRITICAL_SECTION { public : CriticalSection( void ) { InitializeCriticalSection( this ); } ~CriticalSection( void ) { DeleteCriticalSection( this ); } void enter( void ) { EnterCriticalSection( this ); } void leave( void ) { LeaveCriticalSection( this ); } }; class Event { HANDLE hEv; public: Event( BOOL bManualReset = FALSE, BOOL bInitialState = FALSE, LPTSTR lpName = 0 ) { hEv = CreateEvent( 0, bManualReset, bInitialState, lpName ); } void reset( void ) { ResetEvent( hEv ); } void set( void ) { SetEvent( hEv ); } void pulse( void ) { PulseEvent( hEv ); } HANDLE handle( void ) { return hEv; } }; class BufferCounter : public CriticalSection { Event notEmpty; Event notFull[ 2 ]; USHORT maxCnt; USHORT cnt; public: BufferCounter( USHORT maxCount ) { maxCnt = maxCount; cnt = 0; } SHORT getCnt() { return cnt; } void reset( void ); DWORD waitWhileFull( DWORD msec = INFINITE ); DWORD waitWhileEmpty( DWORD msec = INFINITE ); void wakeInserter( void ) { PulseEvent( notFull[0].handle()); } USHORT operator++(); USHORT operator--(); }; void BufferCounter::reset( void ) { notEmpty.reset(); notFull[0].reset(); notFull[1].pulse(); cnt = 0; } DWORD BufferCounter::waitWhileFull( DWORD msec ) { return cnt < maxCnt ? WAIT_OBJECT_0 : WaitForMultipleObjects( 2, (HANDLE *)notFull, 0, msec ); } DWORD BufferCounter::waitWhileEmpty( DWORD msec ) { return cnt != 0 ? WAIT_OBJECT_0 : WaitForSingleObject( notEmpty.handle(), msec ); } USHORT BufferCounter::operator++() { enter(); if( ++cnt == 1 ) notEmpty.set(); leave(); return cnt; // not atomic } USHORT BufferCounter::operator--() { enter(); if( --cnt == maxCnt - 1 ) notFull[0].set(); leave(); return cnt; // not atomic }