Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <cassert>
- #include <exception>
- #if !defined(NDEBUG)
- #define ONDEBUG(expr) (expr)
- #else
- #define ONDEBUG(expr) ((void)0)
- #endif
- class Exception : public std::exception
- {
- };
- class ResourceException : Exception
- {
- };
- template <typename TYPE>
- inline
- TYPE AutoThrowResourceException( TYPE t )
- {
- if( !t )
- throw ResourceException();
- return t;
- }
- class XHANDLE
- {
- public:
- XHANDLE( HANDLE h = NULL );
- XHANDLE();
- ~XHANDLE();
- void CloseHandle();
- public:
- HANDLE h;
- };
- inline
- XHANDLE::XHANDLE( HANDLE h )
- {
- this->h = h;
- }
- inline
- XHANDLE::~XHANDLE()
- {
- BOOL fClosed;
- if( h && h != INVALID_HANDLE_VALUE )
- fClosed = ::CloseHandle( h ),
- assert(fClosed);
- }
- inline
- void XHANDLE::CloseHandle()
- {
- ::CloseHandle( h );
- h = NULL;
- }
- class CondVar
- {
- public:
- CondVar();
- ~CondVar();
- void Enter();
- void Wait();
- void Release();
- void ReleaseAll();
- void Leave();
- private:
- union
- {
- LONG volatile m_lMutex;
- DWORD volatile m_dwOwnerCounter;
- };
- DWORD volatile m_dwWaitingForSignal;
- #if !defined(NDEBUG)
- DWORD volatile m_dwOwningThreadId;
- #endif
- XHANDLE m_xhEvtEnter,
- m_xhSemRelease;
- };
- CondVar::CondVar() :
- m_xhEvtEnter( AutoThrowResourceException( ::CreateEvent( NULL, FALSE, FALSE, NULL ) ) ),
- m_xhSemRelease( AutoThrowResourceException( ::CreateSemaphore( NULL, 0, 0x7FFFFFFF, NULL ) ) )
- {
- ONDEBUG(m_dwOwningThreadId = 0);
- m_lMutex = 0;
- m_dwWaitingForSignal = 0;
- }
- CondVar::~CondVar()
- {
- }
- void CondVar::Enter()
- {
- LONG lMutex,
- lMtxPrevOrChanged;
- for( lMutex = m_lMutex; ; lMutex = lMtxPrevOrChanged )
- if( (lMtxPrevOrChanged = ::InterlockedCompareExchange( &m_lMutex, lMutex + 1, lMutex )) != lMutex )
- continue;
- if( lMutex != 0 )
- {
- for( ; ::WaitForSingleObject( m_xhEvtEnter.h, INFINITE ) != WAIT_OBJECT_0; assert(false) );
- assert(m_lMutex != 0);
- }
- ONDEBUG(m_dwOwningThreadId = GetCurrentThreadId());
- }
- void CondVar::Wait()
- {
- DWORD dwOwnerCounter = (DWORD)m_dwOwnerCounter,
- dwWaitingForSignal = ++m_dwWaitingForSignal;
- assert(dwOwnerCounter >= dwWaitingForSignal);
- assert(m_dwOwningThreadId == GetCurrentThreadId());
- ONDEBUG(m_dwOwningThreadId = 0);
- if( dwOwnerCounter > dwWaitingForSignal )
- for( ; !::SetEvent( m_xhEvtEnter.h ); assert(false) );
- HANDLE ahWait[2] = { m_xhEvtEnter.h, m_xhSemRelease.h };
- for( ; ::WaitForMultipleObjects( 2, ahWait, TRUE, INFINITE ) != WAIT_OBJECT_0; assert(false) );
- assert(m_dwOwnerCounter > m_dwWaitingForSignal);
- ONDEBUG(m_dwOwningThreadId = GetCurrentThreadId());
- }
- void CondVar::Release()
- {
- assert(m_dwOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
- if( m_dwWaitingForSignal != 0 )
- {
- m_dwWaitingForSignal--;
- for( ; !::ReleaseSemaphore( m_xhSemRelease.h, 1, NULL ); assert(false) );
- }
- }
- void CondVar::ReleaseAll()
- {
- DWORD dwWaitingForSignal;
- assert(m_dwOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
- if( (dwWaitingForSignal = m_dwWaitingForSignal) != 0 )
- {
- m_dwWaitingForSignal = 0;
- for( ; !::ReleaseSemaphore( m_xhSemRelease.h, (LONG)dwWaitingForSignal, NULL ); assert(false) );
- }
- }
- void CondVar::Leave()
- {
- LONG lMutex,
- lMtxPrevOrChanged;
- DWORD dwOwnerCounter,
- dwWaitingForSignal;
- assert(m_dwOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
- ONDEBUG(m_dwOwningThreadId = 0);
- for( lMutex = m_lMutex; ; lMutex = lMtxPrevOrChanged )
- {
- dwOwnerCounter = (DWORD)lMutex,
- dwWaitingForSignal = m_dwWaitingForSignal;
- assert(dwOwnerCounter > dwWaitingForSignal);
- if( (lMtxPrevOrChanged = ::InterlockedCompareExchange( &m_lMutex, (LONG)--dwOwnerCounter, lMutex )) == lMutex )
- break;
- }
- if( dwOwnerCounter > dwWaitingForSignal )
- for( ; !::SetEvent( m_xhEvtEnter.h ); assert(false) );
- }
Advertisement
Add Comment
Please, Sign In to add comment