+#include "SGThread.hxx"
+
+#ifdef _WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+/// win32 threads
+/////////////////////////////////////////////////////////////////////////////
+
+#include <list>
+#include <windows.h>
+
+struct SGThread::PrivateData {
+ PrivateData() :
+ _handle(INVALID_HANDLE_VALUE)
+ {
+ }
+ ~PrivateData()
+ {
+ if (_handle == INVALID_HANDLE_VALUE)
+ return;
+ CloseHandle(_handle);
+ _handle = INVALID_HANDLE_VALUE;
+ }
+
+ static DWORD WINAPI start_routine(LPVOID data)
+ {
+ SGThread* thread = reinterpret_cast<SGThread*>(data);
+ thread->run();
+ return 0;
+ }
+
+ bool start(SGThread& thread)
+ {
+ if (_handle != INVALID_HANDLE_VALUE)
+ return false;
+ _handle = CreateThread(0, 0, start_routine, &thread, 0, 0);
+ if (_handle == INVALID_HANDLE_VALUE)
+ return false;
+ return true;
+ }
+
+ void join()
+ {
+ if (_handle == INVALID_HANDLE_VALUE)
+ return;
+ DWORD ret = WaitForSingleObject(_handle, INFINITE);
+ if (ret != WAIT_OBJECT_0)
+ return;
+ CloseHandle(_handle);
+ _handle = INVALID_HANDLE_VALUE;
+ }
+
+ HANDLE _handle;
+};
+
+struct SGMutex::PrivateData {
+ PrivateData()
+ {
+ InitializeCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+ }
+
+ ~PrivateData()
+ {
+ DeleteCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+ }
+
+ void lock(void)
+ {
+ EnterCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+ }
+
+ void unlock(void)
+ {
+ LeaveCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+ }
+
+ CRITICAL_SECTION _criticalSection;
+};
+
+struct SGWaitCondition::PrivateData {
+ ~PrivateData(void)
+ {
+ // The waiters list should be empty anyway
+ _mutex.lock();
+ while (!_pool.empty()) {
+ CloseHandle(_pool.front());
+ _pool.pop_front();
+ }
+ _mutex.unlock();
+ }
+
+ void signal(void)
+ {
+ _mutex.lock();
+ if (!_waiters.empty())
+ SetEvent(_waiters.back());
+ _mutex.unlock();
+ }
+
+ void broadcast(void)
+ {
+ _mutex.lock();
+ for (std::list<HANDLE>::iterator i = _waiters.begin(); i != _waiters.end(); ++i)
+ SetEvent(*i);
+ _mutex.unlock();
+ }
+
+ bool wait(SGMutex::PrivateData& externalMutex, DWORD msec)
+ {
+ _mutex.lock();
+ if (_pool.empty())
+ _waiters.push_front(CreateEvent(NULL, FALSE, FALSE, NULL));
+ else
+ _waiters.splice(_waiters.begin(), _pool, _pool.begin());
+ std::list<HANDLE>::iterator i = _waiters.begin();
+ _mutex.unlock();
+
+ externalMutex.unlock();
+
+ DWORD result = WaitForSingleObject(*i, msec);
+
+ externalMutex.lock();
+
+ _mutex.lock();
+ if (result != WAIT_OBJECT_0)
+ result = WaitForSingleObject(*i, 0);
+ _pool.splice(_pool.begin(), _waiters, i);
+ _mutex.unlock();
+
+ return result == WAIT_OBJECT_0;
+ }
+
+ void wait(SGMutex::PrivateData& externalMutex)
+ {
+ wait(externalMutex, INFINITE);
+ }
+
+ // Protect the list of waiters
+ SGMutex::PrivateData _mutex;
+
+ std::list<HANDLE> _waiters;
+ std::list<HANDLE> _pool;
+};
+