Listing 2: Win32Synchronizer.h

/*===========================================================*\
    Class to allow blocking on any Win32 synchronization handle
    such as events, semaphores, process handles, etc.
\*===========================================================*/
#if !defined(__WIN32_EVENT_SYNCHRONIZER_H__)
#define __WIN32_EVENT_SYNCHRONIZER_H__

#include <windows.h>

namespace Tx
{
    template <class Exception, class Mutex>
    class Win32Synchronizer
    {
      public:
        typedef HANDLE      SyncObject_t; // What to wait on
        typedef Exception   Exception_t;
        typedef DWORD       TimeDuration_t;
        typedef Mutex       Mutex_t;

        enum {TIME_INFINITE = INFINITE};

        Win32Synchronizer()
        {
            _signalObject = 
                ::CreateEvent(NULL, true, false, NULL);
        }

        virtual ~Win32Synchronizer()        
        {
            ::CloseHandle(_signalObject);
        }

        //-----------------------------------------------------
        // Blocking interruptible wait for syncObject
        bool Wait(  const SyncObject_t & syncObject, 
                    TimeDuration_t timeout
                ) const 
        {
            SyncObject_t    handles[2];
            handles[0] = _signalObject;
            handles[1] = syncObject;
            return WaitImpl(handles, 2, timeout);
        }

        //-----------------------------------------------------
        // Blocking idle sleep that is interruptible
        void Sleep(TimeDuration_t timeout) const    
        {
            WaitImpl(&_signalObject, 1, timeout);
        }

        void Signal()
        {
            ::SetEvent(_signalObject);
        }
        
        void Reset()
        {
            ::ResetEvent(_signalObject);
        }

      private:
        //-----------------------------------------------------
        // Actual implementation of "multiple listening" wait
        // behavior relying on WaitForMultipleObjects().
        bool WaitImpl(  
                const SyncObject_t * handles,
                int numHandles,
                TimeDuration_t timeout  // ms or TIME_INFINITE
            ) const
        {
            // Wait on both event objects simultaneously
            DWORD status = ::WaitForMultipleObjects(
                    numHandles, handles, false, timeout
                );

            if (status == WAIT_TIMEOUT)
                return false;   // Nothing happened
            else if (status == WAIT_OBJECT_0)
                throw Exception_t();    // Thread signalled
            else if (status == (WAIT_OBJECT_0 + 1))
                return true;    // Desired event is signaled
            else if (status == WAIT_ABANDONED_0)
                throw Exception_t();// signal event abandoned
            else
                return true;    // Desired event is abandoned
            }

        // Disallow copy constructor/assignment operators
        Win32Synchronizer(const Win32Synchronizer &);
        Win32Synchronizer & operator=(
                const Win32Synchronizer &);

        SyncObject_t        _signalObject;
    };
}

#endif // __WIN32_EVENT_SYNCHRONIZER_H__