Guest User

even simpler condvar vor C++/Win32

a guest
May 19th, 2016
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <windows.h>
  2. #include <cassert>
  3. #include <exception>
  4.  
  5. #if !defined(NDEBUG)
  6.     #define ONDEBUG(expr) (expr)
  7. #else
  8.     #define ONDEBUG(expr) ((void)0)
  9. #endif
  10.  
  11. class Exception : public std::exception
  12. {
  13. };
  14.  
  15. class ResourceException : Exception
  16. {
  17. };
  18.  
  19. template <typename TYPE>
  20. inline
  21. TYPE AutoThrowResourceException( TYPE t )
  22. {
  23.     if( !t )
  24.         throw ResourceException();
  25.  
  26.     return t;
  27. }
  28.  
  29. class XHANDLE
  30. {
  31. public:
  32.          XHANDLE( HANDLE h = NULL );
  33.          XHANDLE();
  34.          ~XHANDLE();
  35.     void CloseHandle();
  36.  
  37. public:
  38.     HANDLE h;
  39. };
  40.  
  41. inline
  42. XHANDLE::XHANDLE( HANDLE h )
  43. {
  44.     this->h = h;
  45. }
  46.  
  47. inline
  48. XHANDLE::~XHANDLE()
  49. {
  50.     BOOL fClosed;
  51.  
  52.     if( h && h != INVALID_HANDLE_VALUE )
  53.         fClosed = ::CloseHandle( h ),
  54.         assert(fClosed);
  55. }
  56.  
  57. inline
  58. void XHANDLE::CloseHandle()
  59. {
  60.     ::CloseHandle( h );
  61.     h = NULL;
  62. }
  63.  
  64.  
  65. class CondVar
  66. {
  67. public:
  68.     CondVar();
  69.     ~CondVar();
  70.     void Enter();
  71.     void Wait();
  72.     void Release();
  73.     void ReleaseAll();
  74.     void Leave();
  75.  
  76. public:
  77.     class Guard;
  78.     class ReverseGuard;
  79.  
  80. private:
  81.     LONG volatile     m_lOwnerCounter;
  82.     DWORD volatile    m_dwWaitingForSignal;
  83. #if !defined(NDEBUG)
  84.     DWORD volatile    m_dwOwningThreadId;
  85. #endif
  86.     XHANDLE           m_xhEvtEnter,
  87.                       m_xhSemRelease;
  88. };
  89.  
  90.  
  91. CondVar::CondVar() :
  92.     m_xhEvtEnter(   AutoThrowResourceException( ::CreateEvent( NULL, FALSE, FALSE, NULL ) ) ),
  93.     m_xhSemRelease( AutoThrowResourceException( ::CreateSemaphore( NULL, 0, 0x7FFFFFFF, NULL ) ) )
  94. {
  95.     ONDEBUG(m_dwOwningThreadId = 0);
  96.  
  97.     m_lOwnerCounter      = 0;
  98.     m_dwWaitingForSignal = 0;
  99. }
  100.  
  101. CondVar::~CondVar()
  102. {
  103. }
  104.  
  105. void CondVar::Enter()
  106. {
  107.     if( (DWORD)::InterlockedIncrement( &m_lOwnerCounter ) > 1 )
  108.         for( ; ::WaitForSingleObject( m_xhEvtEnter.h, INFINITE ) != WAIT_OBJECT_0; assert(false) );
  109.  
  110.     assert(m_lOwnerCounter != 0 && m_dwOwningThreadId == 0);
  111.     ONDEBUG(m_dwOwningThreadId = GetCurrentThreadId());
  112. }
  113.  
  114. void CondVar::Wait()
  115. {
  116.     DWORD dwOwnerCounter     = (DWORD)m_lOwnerCounter,
  117.         dwWaitingForSignal = ++m_dwWaitingForSignal;
  118.  
  119.     assert(dwOwnerCounter >= dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
  120.     ONDEBUG(m_dwOwningThreadId = 0);
  121.  
  122.     if( dwOwnerCounter > dwWaitingForSignal )
  123.         for( ; !::SetEvent( m_xhEvtEnter.h ); assert(false) );
  124.  
  125.     HANDLE ahWait[2] = { m_xhEvtEnter.h, m_xhSemRelease.h };
  126.  
  127.     for( ; ::WaitForMultipleObjects( 2, ahWait, TRUE, INFINITE ) != WAIT_OBJECT_0; assert(false) );
  128.     assert((DWORD)m_lOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == 0);
  129.     ONDEBUG(m_dwOwningThreadId = GetCurrentThreadId());
  130. }
  131.  
  132. void CondVar::Release()
  133. {
  134.     assert((DWORD)m_lOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
  135.  
  136.     if( m_dwWaitingForSignal != 0 )
  137.     {
  138.         m_dwWaitingForSignal--;
  139.         for( ; !::ReleaseSemaphore( m_xhSemRelease.h, 1, NULL ); assert(false) );
  140.     }
  141. }
  142.  
  143. void CondVar::ReleaseAll()
  144. {
  145.     DWORD dwWaitingForSignal;
  146.  
  147.     assert((DWORD)m_lOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
  148.  
  149.     if( (dwWaitingForSignal = m_dwWaitingForSignal) != 0 )
  150.     {
  151.         m_dwWaitingForSignal = 0;
  152.         for( ; !::ReleaseSemaphore( m_xhSemRelease.h, (LONG)dwWaitingForSignal, NULL ); assert(false) );
  153.     }
  154. }
  155.  
  156. void CondVar::Leave()
  157. {
  158.     assert((DWORD)m_lOwnerCounter > m_dwWaitingForSignal && m_dwOwningThreadId == GetCurrentThreadId());
  159.     ONDEBUG(m_dwOwningThreadId = 0);
  160.  
  161.     DWORD dwOwnerCounter = (DWORD)::InterlockedDecrement( &m_lOwnerCounter );
  162.  
  163.     if( dwOwnerCounter > m_dwWaitingForSignal )
  164.         for( ; !::SetEvent( m_xhEvtEnter.h ); assert(false) );
  165. }
Advertisement
Add Comment
Please, Sign In to add comment