summaryrefslogtreecommitdiff
path: root/libs/ode-0.16.1/ode/src/threading_impl_win.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ode-0.16.1/ode/src/threading_impl_win.h')
-rw-r--r--libs/ode-0.16.1/ode/src/threading_impl_win.h273
1 files changed, 273 insertions, 0 deletions
diff --git a/libs/ode-0.16.1/ode/src/threading_impl_win.h b/libs/ode-0.16.1/ode/src/threading_impl_win.h
new file mode 100644
index 0000000..f3cb489
--- /dev/null
+++ b/libs/ode-0.16.1/ode/src/threading_impl_win.h
@@ -0,0 +1,273 @@
+/*************************************************************************
+ * *
+ * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org *
+ * *
+ * Threading Windows implementation file. *
+ * Copyright (C) 2011-2019 Oleh Derevenko. All rights reserved. *
+ * e-mail: odar@eleks.com (change all "a" to "e") *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of EITHER: *
+ * (1) The GNU Lesser General Public License as published by the Free *
+ * Software Foundation; either version 2.1 of the License, or (at *
+ * your option) any later version. The text of the GNU Lesser *
+ * General Public License is included with this library in the *
+ * file LICENSE.TXT. *
+ * (2) The BSD-style license that is included with this library in *
+ * the file LICENSE-BSD.TXT. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
+ * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
+ * *
+ *************************************************************************/
+
+/*
+ * Threading Windows implementation for built-in threading support provider.
+ */
+
+
+#ifndef _ODE_THREADING_IMPL_WIN_H_
+#define _ODE_THREADING_IMPL_WIN_H_
+
+
+#include <ode/common.h>
+
+
+#if defined(_WIN32)
+
+#if dBUILTIN_THREADING_IMPL_ENABLED
+
+#if !defined(_WIN32_WINNT)
+#define _WIN32_WINNT 0x0400
+#endif
+#include <windows.h>
+
+
+#endif // #if dBUILTIN_THREADING_IMPL_ENABLED
+
+
+#include "threading_impl_templates.h"
+#include "threading_fake_sync.h"
+#include "threading_atomics_provs.h"
+
+
+#if dBUILTIN_THREADING_IMPL_ENABLED
+
+/************************************************************************/
+/* dxEventWakeup class implementation */
+/************************************************************************/
+
+class dxEventWakeup
+{
+public:
+ dxEventWakeup(): m_state_is_permanent(false), m_event_handle(NULL) {}
+ ~dxEventWakeup() { DoFinalizeObject(); }
+
+ bool InitializeObject() { return DoInitializeObject(); }
+
+private:
+ bool DoInitializeObject();
+ void DoFinalizeObject();
+
+public:
+ void ResetWakeup();
+ void WakeupAThread();
+ void WakeupAllThreads();
+
+ bool WaitWakeup(const dThreadedWaitTime *timeout_time_ptr);
+
+private:
+ bool m_state_is_permanent;
+ HANDLE m_event_handle;
+};
+
+
+bool dxEventWakeup::DoInitializeObject()
+{
+ dIASSERT(m_event_handle == NULL);
+
+ bool init_result = false;
+
+ do
+ {
+ HANDLE event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (event_handle == NULL)
+ {
+ break;
+ }
+
+ m_event_handle = event_handle;
+ init_result = true;
+ }
+ while (false);
+
+ return init_result;
+}
+
+void dxEventWakeup::DoFinalizeObject()
+{
+ HANDLE event_handle = m_event_handle;
+
+ if (event_handle != NULL)
+ {
+ BOOL close_result = CloseHandle(event_handle);
+ dICHECK(close_result != FALSE);
+
+ m_event_handle = NULL;
+ }
+}
+
+
+void dxEventWakeup::ResetWakeup()
+{
+ // Order of assignment and resetting event is not important but it is preferable to be performed this way.
+ m_state_is_permanent = false;
+
+ BOOL event_set_result = ResetEvent(m_event_handle);
+ dICHECK(event_set_result);
+}
+
+void dxEventWakeup::WakeupAThread()
+{
+ dIASSERT(!m_state_is_permanent); // Wakeup should not be used after permanent signal
+
+ BOOL event_reset_result = SetEvent(m_event_handle);
+ dICHECK(event_reset_result);
+}
+
+void dxEventWakeup::WakeupAllThreads()
+{
+ // Order of assignment and setting event is important!
+ m_state_is_permanent = true;
+
+ BOOL event_set_result = SetEvent(m_event_handle);
+ dICHECK(event_set_result);
+}
+
+
+bool dxEventWakeup::WaitWakeup(const dThreadedWaitTime *timeout_time_ptr)
+{
+ bool wait_result;
+
+ if (timeout_time_ptr == NULL)
+ {
+ DWORD event_wait_result = WaitForSingleObject(m_event_handle, INFINITE);
+ dICHECK(event_wait_result == WAIT_OBJECT_0);
+
+ wait_result = true;
+ }
+ else if (timeout_time_ptr->wait_sec == 0 && timeout_time_ptr->wait_nsec == 0)
+ {
+ DWORD event_wait_result = WaitForSingleObject(m_event_handle, 0);
+
+ wait_result = event_wait_result == WAIT_OBJECT_0;
+ dICHECK(wait_result || event_wait_result == WAIT_TIMEOUT);
+ }
+ else
+ {
+ dIASSERT(timeout_time_ptr->wait_nsec < 1000000000UL);
+
+ const DWORD max_wait_seconds_in_a_shot = ((INFINITE - 1) / 1000U) - 1;
+
+ time_t timeout_seconds_remaining = timeout_time_ptr->wait_sec;
+ DWORD wait_timeout = timeout_time_ptr->wait_nsec != 0 ? ((timeout_time_ptr->wait_nsec + 999999UL) / 1000000UL) : 0;
+
+ while (true)
+ {
+ if (timeout_seconds_remaining >= (time_t)max_wait_seconds_in_a_shot)
+ {
+ wait_timeout += max_wait_seconds_in_a_shot * 1000U;
+ timeout_seconds_remaining -= max_wait_seconds_in_a_shot;
+ }
+ else
+ {
+ wait_timeout += (DWORD)timeout_seconds_remaining * 1000U;
+ timeout_seconds_remaining = 0;
+ }
+
+ DWORD event_wait_result = WaitForSingleObject(m_event_handle, wait_timeout);
+
+ if (event_wait_result == WAIT_OBJECT_0)
+ {
+ wait_result = true;
+ break;
+ }
+
+ dICHECK(event_wait_result == WAIT_TIMEOUT);
+
+ if (timeout_seconds_remaining == 0)
+ {
+ wait_result = false;
+ break;
+ }
+
+ wait_timeout = 0;
+ }
+ }
+
+ if (wait_result && m_state_is_permanent)
+ {
+ // Since event is automatic it is necessary to set it back for the upcoming waiters
+ BOOL event_set_result = SetEvent(m_event_handle);
+ dICHECK(event_set_result);
+ }
+
+ return wait_result;
+}
+
+
+/************************************************************************/
+/* dxCriticalSectionMutex class implementation */
+/************************************************************************/
+
+class dxCriticalSectionMutex
+{
+public:
+ dxCriticalSectionMutex() { InitializeCriticalSection(&m_critical_section); }
+ ~dxCriticalSectionMutex() { DeleteCriticalSection(&m_critical_section); }
+
+ bool InitializeObject() { return true; }
+
+public:
+ void LockMutex() { EnterCriticalSection(&m_critical_section); }
+ bool TryLockMutex() { return TryEnterCriticalSection(&m_critical_section) != FALSE; }
+ void UnlockMutex() { LeaveCriticalSection(&m_critical_section); }
+
+private:
+ CRITICAL_SECTION m_critical_section;
+};
+
+
+#endif // #if dBUILTIN_THREADING_IMPL_ENABLED
+
+
+/************************************************************************/
+/* Self-threaded job list definition */
+/************************************************************************/
+
+typedef dxtemplateJobListContainer<dxFakeLull, dxFakeMutex, dxFakeAtomicsProvider> dxSelfThreadedJobListContainer;
+typedef dxtemplateJobListSelfHandler<dxSelfWakeup, dxSelfThreadedJobListContainer> dxSelfThreadedJobListHandler;
+typedef dxtemplateThreadingImplementation<dxSelfThreadedJobListContainer, dxSelfThreadedJobListHandler> dxSelfThreadedThreading;
+
+
+#if dBUILTIN_THREADING_IMPL_ENABLED
+
+/************************************************************************/
+/* Multi-threaded job list definition */
+/************************************************************************/
+
+typedef dxtemplateJobListContainer<dxtemplateThreadedLull<dxEventWakeup, dxOUAtomicsProvider, false>, dxCriticalSectionMutex, dxOUAtomicsProvider> dxMultiThreadedJobListContainer;
+typedef dxtemplateJobListThreadedHandler<dxEventWakeup, dxMultiThreadedJobListContainer> dxMultiThreadedJobListHandler;
+typedef dxtemplateThreadingImplementation<dxMultiThreadedJobListContainer, dxMultiThreadedJobListHandler> dxMultiThreadedThreading;
+
+
+#endif // #if dBUILTIN_THREADING_IMPL_ENABLED
+
+
+#endif // #if defined(_WIN32)
+
+
+#endif // #ifndef _ODE_THREADING_IMPL_WIN_H_