diff options
author | sanine <sanine.not@pm.me> | 2022-10-01 20:59:36 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2022-10-01 20:59:36 -0500 |
commit | c5fc66ee58f2c60f2d226868bb1cf5b91badaf53 (patch) | |
tree | 277dd280daf10bf77013236b8edfa5f88708c7e0 /libs/ode-0.16.1/ode/src/threading_base.h | |
parent | 1cf9cc3408af7008451f9133fb95af66a9697d15 (diff) |
add ode
Diffstat (limited to 'libs/ode-0.16.1/ode/src/threading_base.h')
-rw-r--r-- | libs/ode-0.16.1/ode/src/threading_base.h | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/libs/ode-0.16.1/ode/src/threading_base.h b/libs/ode-0.16.1/ode/src/threading_base.h new file mode 100644 index 0000000..cb38f7f --- /dev/null +++ b/libs/ode-0.16.1/ode/src/threading_base.h @@ -0,0 +1,291 @@ +/************************************************************************* + * * + * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * + * All rights reserved. Email: russ@q12.org Web: www.q12.org * + * * + * Threading base wrapper class header 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 base class to be used for inheritance by dxWorld, dxSpace and others + * to take advantage of threaded execution. + */ + + +#ifndef _ODE_THREADING_BASE_H_ +#define _ODE_THREADING_BASE_H_ + + +#include "common.h" +#include <ode/threading.h> + + +struct dxIThreadingDefaultImplProvider +{ +public: + virtual const dxThreadingFunctionsInfo *retrieveThreadingDefaultImpl(dThreadingImplementationID &out_defaultImpl) = 0; +}; + + +class dxThreadingBase +{ +protected: + dxThreadingBase(): + m_default_impl_provider(NULL), + m_functions_info(NULL), + m_threading_impl(NULL), + m_stock_call_wait(NULL) + { + } + + // This ought to be done via constructor, but passing 'this' in base class initializer emits a warning in MSVC :( + void setThreadingDefaultImplProvider(dxIThreadingDefaultImplProvider *default_impl_provider) + { + m_default_impl_provider = default_impl_provider; + dIASSERT(GetStockCallWait() == NULL); + } + + ~dxThreadingBase(); + +public: + void assignThreadingImpl(const dxThreadingFunctionsInfo *functions_info, dThreadingImplementationID threading_impl) + { + dAASSERT((functions_info == NULL) == (threading_impl == NULL)); + + // Free the stock call wait first to have it executed before new pointer values are assigned + DoFreeStockCallWait(); + + m_functions_info = functions_info; + m_threading_impl = threading_impl; + } + +public: + unsigned calculateThreadingLimitedThreadCount(unsigned limitValue, bool countCallerAsExtraThread, unsigned *ptrOut_activeThreadCount=NULL) const + { + unsigned activeThreadCount = RetrieveThreadingThreadCount(); + + if (ptrOut_activeThreadCount != NULL) + { + *ptrOut_activeThreadCount = activeThreadCount; + } + + unsigned adjustedActiveThreads = countCallerAsExtraThread && activeThreadCount != UINT_MAX ? activeThreadCount + 1 : activeThreadCount; + return limitValue == dTHREADING_THREAD_COUNT_UNLIMITED + ? adjustedActiveThreads + : dMACRO_MIN(limitValue, adjustedActiveThreads); + } + +public: + dCallWaitID AllocateOrRetrieveStockCallWaitID() + { + dCallWaitID stock_wait_id = GetStockCallWait(); + return stock_wait_id != NULL ? (ResetThreadedCallWait(stock_wait_id), stock_wait_id) : DoAllocateStockCallWait(); + } + +public: + dMutexGroupID AllocMutexGroup(dmutexindex_t Mutex_count, const char *const *Mutex_names_ptr/*=NULL*/) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + return functions->alloc_mutex_group(impl, Mutex_count, Mutex_names_ptr); + } + + void FreeMutexGroup(dMutexGroupID mutex_group) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->free_mutex_group(impl, mutex_group); + } + + void LockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->lock_group_mutex(impl, mutex_group, mutex_index); + } + +// bool TryLockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const +// { +// dThreadingImplementationID impl; +// const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); +// return functions->trylock_group_mutex(impl, mutex_group, mutex_index) != 0; +// } + + void UnlockMutexGroupMutex(dMutexGroupID mutex_group, dmutexindex_t mutex_index) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->unlock_group_mutex(impl, mutex_group, mutex_index); + } + + dCallWaitID AllocThreadedCallWait() const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + return functions->alloc_call_wait(impl); + } + + void ResetThreadedCallWait(dCallWaitID call_wait) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->reset_call_wait(impl, call_wait); + } + + void FreeThreadedCallWait(dCallWaitID call_wait) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->free_call_wait(impl, call_wait); + } + + void PostThreadedCall(int *out_summary_fault/*=NULL*/, + dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, + dCallWaitID call_wait/*=NULL*/, + dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, + const char *call_name/*=NULL*/) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->post_call(impl, out_summary_fault, out_post_releasee, dependencies_count, dependent_releasee, call_wait, call_func, call_context, instance_index, call_name); + } + + void AlterThreadedCallDependenciesCount(dCallReleaseeID target_releasee, + ddependencychange_t dependencies_count_change) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->alter_call_dependencies_count(impl, target_releasee, dependencies_count_change); + } + + void WaitThreadedCallExclusively(int *out_wait_status/*=NULL*/, + dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, + const char *wait_name/*=NULL*/) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name); + functions->reset_call_wait(impl, call_wait); + } + + void WaitThreadedCallCollectively(int *out_wait_status/*=NULL*/, + dCallWaitID call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/, + const char *wait_name/*=NULL*/) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + functions->wait_call(impl, out_wait_status, call_wait, timeout_time_ptr, wait_name); + } + + unsigned RetrieveThreadingThreadCount() const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + return functions->retrieve_thread_count(impl); + } + + bool PreallocateResourcesForThreadedCalls(unsigned max_simultaneous_calls_estimate) const + { + dThreadingImplementationID impl; + const dxThreadingFunctionsInfo *functions = FindThreadingImpl(impl); + return functions->preallocate_resources_for_calls(impl, max_simultaneous_calls_estimate) != 0; + } + +public: + void PostThreadedCallsGroup(int *out_summary_fault/*=NULL*/, + ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, + dThreadedCallFunction *call_func, void *call_context, + const char *call_name/*=NULL*/) const; + void PostThreadedCallsIndexOverridenGroup(int *out_summary_fault/*=NULL*/, + ddependencycount_t member_count, dCallReleaseeID dependent_releasee/*=NULL*/, + dThreadedCallFunction *call_func, void *call_context, unsigned index_override, + const char *call_name/*=NULL*/) const; + void PostThreadedCallForUnawareReleasee(int *out_summary_fault/*=NULL*/, + dCallReleaseeID *out_post_releasee/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/, + dCallWaitID call_wait/*=NULL*/, + dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index, + const char *call_name/*=NULL*/) const; + +protected: + const dxThreadingFunctionsInfo *FindThreadingImpl(dThreadingImplementationID &out_impl_found) const; + +private: + dCallWaitID DoAllocateStockCallWait(); + void DoFreeStockCallWait(); + +private: + const dxThreadingFunctionsInfo *GetFunctionsInfo() const { return m_functions_info; } + dThreadingImplementationID GetThreadingImpl() const { return m_threading_impl; } + + void SetStockCallWait(dCallWaitID value) { m_stock_call_wait = value; } + dCallWaitID GetStockCallWait() const { return m_stock_call_wait; } + +private: + dxIThreadingDefaultImplProvider *m_default_impl_provider; + const dxThreadingFunctionsInfo *m_functions_info; + dThreadingImplementationID m_threading_impl; + dCallWaitID m_stock_call_wait; +}; + +class dxMutexGroupLockHelper +{ +public: + dxMutexGroupLockHelper(dxThreadingBase *threading_base, dMutexGroupID mutex_group, dmutexindex_t mutex_index): + m_threading_base(threading_base), + m_mutex_group(mutex_group), + m_mutex_index(mutex_index), + m_mutex_locked(true) + { + threading_base->LockMutexGroupMutex(mutex_group, mutex_index); + } + + ~dxMutexGroupLockHelper() + { + if (m_mutex_locked) + { + m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index); + } + } + + void UnlockMutex() + { + dIASSERT(m_mutex_locked); + + m_threading_base->UnlockMutexGroupMutex(m_mutex_group, m_mutex_index); + m_mutex_locked = false; + } + + void RelockMutex() + { + dIASSERT(!m_mutex_locked); + + m_threading_base->LockMutexGroupMutex(m_mutex_group, m_mutex_index); + m_mutex_locked = true; + } + +private: + dxThreadingBase *m_threading_base; + dMutexGroupID m_mutex_group; + dmutexindex_t m_mutex_index; + bool m_mutex_locked; +}; + +#endif // #ifndef _ODE_THREADING_BASE_H_ |