| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265 |
- /*************************************************************************
- * *
- * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
- * All rights reserved. Email: [email protected] Web: www.q12.org *
- * *
- * Threading implementation templates file. *
- * Copyright (C) 2011-2012 Oleh Derevenko. All rights reserved. *
- * e-mail: [email protected] (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. *
- * *
- *************************************************************************/
- /*
- * Job list and Mutex group implementation templates for built-in threading
- * support provider.
- */
- #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_
- #define _ODE_THREADING_IMPL_TEMPLATES_H_
- #include <ode/common.h>
- #include <ode/memory.h>
- #include <ode/threading.h>
- #include "objects.h"
- #include <new>
- #define dMAKE_JOBINSTANCE_RELEASEE(job_instance) ((dCallReleaseeID)(job_instance))
- #define dMAKE_RELEASEE_JOBINSTANCE(releasee) ((dxThreadedJobInfo *)(releasee))
- template <class tThreadMutex>
- class dxtemplateMutexGroup
- {
- private:
- dxtemplateMutexGroup() {}
- ~dxtemplateMutexGroup() {}
- public:
- static dxtemplateMutexGroup<tThreadMutex> *AllocateInstance(dmutexindex_t Mutex_count);
- static void FreeInstance(dxtemplateMutexGroup<tThreadMutex> *mutex_group);
- private:
- bool InitializeMutexArray(dmutexindex_t Mutex_count);
- void FinalizeMutexArray(dmutexindex_t Mutex_count);
- public:
- void LockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].LockMutex(); }
- bool TryLockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); return m_Mutex_array[mutex_index].TryLockMutex(); }
- void UnlockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].UnlockMutex(); }
- private:
- union
- {
- dmutexindex_t m_mutex_count;
- unsigned long m_reserved_for_allignment[2];
- } m_un;
- tThreadMutex m_Mutex_array[1];
- };
- template<class tThreadWakeup>
- class dxtemplateCallWait:
- public dBase
- {
- public:
- dxtemplateCallWait() {}
- ~dxtemplateCallWait() { DoFinalizeObject(); }
- bool InitializeObject() { return DoInitializeObject(); }
- private:
- bool DoInitializeObject() { return m_wait_wakeup.InitializeObject(); }
- void DoFinalizeObject() { /* Do nothing */ }
- public:
- typedef dxtemplateCallWait<tThreadWakeup> dxCallWait;
- public:
- void ResetTheWait() { m_wait_wakeup.ResetWakeup(); }
- void SignalTheWait() { m_wait_wakeup.WakeupAllThreads(); }
- bool PerformWaiting(const dThreadedWaitTime *timeout_time_ptr/*=NULL*/) { return m_wait_wakeup.WaitWakeup(timeout_time_ptr); }
- public:
- static void AbstractSignalTheWait(void *wait_wakeup_ptr) { ((dxCallWait *)wait_wakeup_ptr)->SignalTheWait(); }
- private:
- tThreadWakeup m_wait_wakeup;
- };
- #if dBUILTIN_THREADING_IMPL_ENABLED
- template<class tThreadWakeup, class tAtomicsProvider, const bool tatomic_test_required>
- class dxtemplateThreadedLull
- {
- public:
- dxtemplateThreadedLull(): m_registrant_count(0), m_alarm_wakeup() {}
- ~dxtemplateThreadedLull() { dIASSERT(m_registrant_count == 0); DoFinalizeObject(); }
- bool InitializeObject() { return DoInitializeObject(); }
- private:
- bool DoInitializeObject() { return m_alarm_wakeup.InitializeObject(); }
- void DoFinalizeObject() { /* Do nothing */ }
- private:
- typedef typename tAtomicsProvider::atomicord_t atomicord_t;
- public:
- void RegisterToLull() { tAtomicsProvider::IncrementTargetNoRet(&m_registrant_count); }
- void WaitForLullAlarm() { dIASSERT(m_registrant_count != 0); m_alarm_wakeup.WaitWakeup(NULL); }
- void UnregisterFromLull() { tAtomicsProvider::DecrementTargetNoRet(&m_registrant_count); }
- void SignalLullAlarmIfAnyRegistrants()
- {
- if (tatomic_test_required ? (tAtomicsProvider::QueryTargetValue(&m_registrant_count) != 0) : (m_registrant_count != 0))
- {
- m_alarm_wakeup.WakeupAThread();
- }
- }
- private:
- atomicord_t m_registrant_count;
- tThreadWakeup m_alarm_wakeup;
- };
- #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
- struct dxThreadedJobInfo:
- public dBase
- {
- dxThreadedJobInfo() {}
- explicit dxThreadedJobInfo(void *): m_next_job(NULL) {}
- void AssignJobData(ddependencycount_t dependencies_count, dxThreadedJobInfo *dependent_job, void *call_wait,
- int *fault_accumulator_ptr, dThreadedCallFunction *call_function, void *call_context, dcallindex_t call_index)
- {
- m_dependencies_count = dependencies_count;
- m_dependent_job = dependent_job;
- m_call_wait = call_wait;
- m_fault_accumulator_ptr = fault_accumulator_ptr;
- m_call_fault = 0;
- m_call_function = call_function;
- m_call_context = call_context;
- m_call_index = call_index;
- }
- bool InvokeCallFunction()
- {
- int call_result = m_call_function(m_call_context, m_call_index, dMAKE_JOBINSTANCE_RELEASEE(this));
- return call_result != 0;
- }
- dxThreadedJobInfo *m_next_job;
- dxThreadedJobInfo **m_prev_job_next_ptr;
- ddependencycount_t m_dependencies_count;
- dxThreadedJobInfo *m_dependent_job;
- void *m_call_wait;
- int *m_fault_accumulator_ptr;
- int m_call_fault;
- dThreadedCallFunction *m_call_function;
- void *m_call_context;
- dcallindex_t m_call_index;
- };
- template<class tThreadMutex>
- class dxtemplateThreadingLockHelper
- {
- public:
- dxtemplateThreadingLockHelper(tThreadMutex &mutex_instance): m_mutex_instance(mutex_instance), m_lock_indicator_flag(false) { LockMutex(); }
- ~dxtemplateThreadingLockHelper() { if (m_lock_indicator_flag) { UnlockMutex(); } }
- void LockMutex() { dIASSERT(!m_lock_indicator_flag); m_mutex_instance.LockMutex(); m_lock_indicator_flag = true; }
- void UnlockMutex() { dIASSERT(m_lock_indicator_flag); m_mutex_instance.UnlockMutex(); m_lock_indicator_flag = false; }
- private:
- tThreadMutex &m_mutex_instance;
- bool m_lock_indicator_flag;
- };
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- class dxtemplateJobListContainer
- {
- public:
- dxtemplateJobListContainer():
- m_job_list(NULL),
- m_info_pool((atomicptr_t)NULL),
- m_pool_access_lock(),
- m_list_access_lock(),
- m_info_wait_lull(),
- m_info_count_known_to_be_preallocated(0)
- {
- }
- ~dxtemplateJobListContainer()
- {
- dIASSERT(m_job_list == NULL); // Would not it be nice to wait for jobs to complete before deleting the list?
- FreeJobInfoPoolInfos();
- DoFinalizeObject();
- }
- bool InitializeObject() { return DoInitializeObject(); }
- private:
- bool DoInitializeObject() { return m_pool_access_lock.InitializeObject() && m_list_access_lock.InitializeObject() && m_info_wait_lull.InitializeObject(); }
- void DoFinalizeObject() { /* Do nothing */ }
- public:
- typedef tAtomicsProvider dxAtomicsProvider;
- typedef typename tAtomicsProvider::atomicord_t atomicord_t;
- typedef typename tAtomicsProvider::atomicptr_t atomicptr_t;
- typedef tThreadMutex dxThreadMutex;
- typedef dxtemplateThreadingLockHelper<tThreadMutex> dxMutexLockHelper;
- typedef void dWaitSignallingFunction(void *job_call_wait);
- public:
- dxThreadedJobInfo *ReleaseAJobAndPickNextPendingOne(
- dxThreadedJobInfo *job_to_release, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr,
- bool &out_last_job_flag);
- private:
- dxThreadedJobInfo *PickNextPendingJob(bool &out_last_job_flag);
- void ReleaseAJob(dxThreadedJobInfo *job_instance, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr);
- public:
- inline dxThreadedJobInfo *AllocateJobInfoFromPool();
- void QueueJobForProcessing(dxThreadedJobInfo *job_instance);
- void AlterJobProcessingDependencies(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change,
- bool &out_job_has_become_ready);
- private:
- inline ddependencycount_t SmartAddJobDependenciesCount(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change);
- inline void InsertJobInfoIntoListHead(dxThreadedJobInfo *job_instance);
- inline void RemoveJobInfoFromList(dxThreadedJobInfo *job_instance);
- dxThreadedJobInfo *ExtractJobInfoFromPoolOrAllocate();
- inline void ReleaseJobInfoIntoPool(dxThreadedJobInfo *job_instance);
- private:
- void FreeJobInfoPoolInfos();
- public:
- bool EnsureNumberOfJobInfosIsPreallocated(ddependencycount_t required_info_count);
- private:
- bool DoPreallocateJobInfos(ddependencycount_t required_info_count);
- public:
- bool IsJobListReadyForShutdown() const { return m_job_list == NULL; }
- private:
- dxThreadedJobInfo *m_job_list;
- volatile atomicptr_t m_info_pool; // dxThreadedJobInfo *
- tThreadMutex m_pool_access_lock;
- tThreadMutex m_list_access_lock;
- tThreadLull m_info_wait_lull;
- ddependencycount_t m_info_count_known_to_be_preallocated;
- };
- typedef void (dxThreadReadyToServeCallback)(void *callback_context);
- #if dBUILTIN_THREADING_IMPL_ENABLED
- template<class tThreadWakeup, class tJobListContainer>
- class dxtemplateJobListThreadedHandler
- {
- public:
- dxtemplateJobListThreadedHandler(tJobListContainer *list_container_ptr):
- m_job_list_ptr(list_container_ptr),
- m_processing_wakeup(),
- m_active_thread_count(0),
- m_shutdown_requested(0)
- {
- }
- ~dxtemplateJobListThreadedHandler()
- {
- dIASSERT(m_active_thread_count == 0);
- DoFinalizeObject();
- }
- bool InitializeObject() { return DoInitializeObject(); }
- private:
- bool DoInitializeObject() { return m_processing_wakeup.InitializeObject(); }
- void DoFinalizeObject() { /* Do nothing */ }
- public:
- typedef dxtemplateCallWait<tThreadWakeup> dxCallWait;
- public:
- inline void ProcessActiveJobAddition();
- inline void PrepareForWaitingAJobCompletion();
- public:
- inline unsigned RetrieveActiveThreadsCount();
- inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/);
- private:
- void PerformJobProcessingUntilShutdown();
- void PerformJobProcessingSession();
- void BlockAsIdleThread();
- void ActivateAnIdleThread();
- public:
- inline void ShutdownProcessing();
- inline void CleanupForRestart();
- private:
- bool IsShutdownRequested() const { return m_shutdown_requested != 0; }
- private:
- typedef typename tJobListContainer::dxAtomicsProvider dxAtomicsProvider;
- typedef typename tJobListContainer::atomicord_t atomicord_t;
- atomicord_t GetActiveThreadsCount() const { return m_active_thread_count; }
- void RegisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget<sizeof(atomicord_t)>((volatile void *)&m_active_thread_count, 1); }
- void UnregisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget<sizeof(atomicord_t)>((volatile void *)&m_active_thread_count, -1); }
- private:
- tJobListContainer *m_job_list_ptr;
- tThreadWakeup m_processing_wakeup;
- volatile atomicord_t m_active_thread_count;
- int m_shutdown_requested;
- };
- #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
- template<class tThreadWakeup, class tJobListContainer>
- class dxtemplateJobListSelfHandler
- {
- public:
- dxtemplateJobListSelfHandler(tJobListContainer *list_container_ptr):
- m_job_list_ptr(list_container_ptr)
- {
- }
- ~dxtemplateJobListSelfHandler()
- {
- // Do nothing
- }
- bool InitializeObject() { return true; }
- public:
- typedef dxtemplateCallWait<tThreadWakeup> dxCallWait;
- public:
- inline void ProcessActiveJobAddition();
- inline void PrepareForWaitingAJobCompletion();
- public:
- inline unsigned RetrieveActiveThreadsCount();
- inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/);
- private:
- void PerformJobProcessingUntilExhaustion();
- void PerformJobProcessingSession();
- public:
- inline void ShutdownProcessing();
- inline void CleanupForRestart();
- private:
- tJobListContainer *m_job_list_ptr;
- };
- struct dIMutexGroup;
- struct dxICallWait;
- class dxIThreadingImplementation
- {
- public:
- virtual void FreeInstance() = 0;
- public:
- virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count) = 0;
- virtual void FreeMutexGroup(dIMutexGroup *mutex_group) = 0;
- virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0;
- // virtual bool TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0;
- virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0;
- public:
- virtual dxICallWait *AllocACallWait() = 0;
- virtual void ResetACallWait(dxICallWait *call_wait) = 0;
- virtual void FreeACallWait(dxICallWait *call_wait) = 0;
- public:
- virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate) = 0;
- virtual void ScheduleNewJob(int *fault_accumulator_ptr/*=NULL*/,
- dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
- dxICallWait *call_wait/*=NULL*/,
- dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index) = 0;
- virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) = 0;
- virtual void WaitJobCompletion(int *out_wait_status_ptr/*=NULL*/,
- dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/) = 0;
- public:
- virtual unsigned RetrieveActiveThreadsCount() = 0;
- virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/) = 0;
- virtual void ShutdownProcessing() = 0;
- virtual void CleanupForRestart() = 0;
- };
- template<class tJobListContainer, class tJobListHandler>
- class dxtemplateThreadingImplementation:
- public dBase,
- public dxIThreadingImplementation
- {
- public:
- dxtemplateThreadingImplementation():
- dBase(),
- m_list_container(),
- m_list_handler(&m_list_container)
- {
- }
- virtual ~dxtemplateThreadingImplementation()
- {
- DoFinalizeObject();
- }
- bool InitializeObject() { return DoInitializeObject(); }
- private:
- bool DoInitializeObject() { return m_list_container.InitializeObject() && m_list_handler.InitializeObject(); }
- void DoFinalizeObject() { /* Do nothing */ }
- protected:
- virtual void FreeInstance();
- private:
- typedef dxtemplateMutexGroup<typename tJobListContainer::dxThreadMutex> dxMutexGroup;
- typedef typename tJobListHandler::dxCallWait dxCallWait;
- protected:
- virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count);
- virtual void FreeMutexGroup(dIMutexGroup *mutex_group);
- virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index);
- // virtual bool TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index);
- virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index);
- protected:
- virtual dxICallWait *AllocACallWait();
- virtual void ResetACallWait(dxICallWait *call_wait);
- virtual void FreeACallWait(dxICallWait *call_wait);
- protected:
- virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate);
- virtual void ScheduleNewJob(int *fault_accumulator_ptr/*=NULL*/,
- dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
- dxICallWait *call_wait/*=NULL*/,
- dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index);
- virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change);
- virtual void WaitJobCompletion(int *out_wait_status_ptr/*=NULL*/,
- dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/);
- protected:
- virtual unsigned RetrieveActiveThreadsCount();
- virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/);
- virtual void ShutdownProcessing();
- virtual void CleanupForRestart();
- private:
- tJobListContainer m_list_container;
- tJobListHandler m_list_handler;
- };
- /************************************************************************/
- /* Implementation of dxtemplateMutexGroup */
- /************************************************************************/
- template<class tThreadMutex>
- /*static */dxtemplateMutexGroup<tThreadMutex> *dxtemplateMutexGroup<tThreadMutex>::AllocateInstance(dmutexindex_t Mutex_count)
- {
- dAASSERT(Mutex_count != 0);
- const dxtemplateMutexGroup<tThreadMutex> *const dummy_group = (dxtemplateMutexGroup<tThreadMutex> *)(size_t)8;
- const size_t size_requited = ((size_t)(&dummy_group->m_Mutex_array) - (size_t)dummy_group) + Mutex_count * sizeof(tThreadMutex);
- dxtemplateMutexGroup<tThreadMutex> *mutex_group = (dxtemplateMutexGroup<tThreadMutex> *)dAlloc(size_requited);
- if (mutex_group != NULL)
- {
- mutex_group->m_un.m_mutex_count = Mutex_count;
- if (!mutex_group->InitializeMutexArray(Mutex_count))
- {
- dFree((void *)mutex_group, size_requited);
- mutex_group = NULL;
- }
- }
- return mutex_group;
- }
- template<class tThreadMutex>
- /*static */void dxtemplateMutexGroup<tThreadMutex>::FreeInstance(dxtemplateMutexGroup<tThreadMutex> *mutex_group)
- {
- if (mutex_group != NULL)
- {
- dmutexindex_t Mutex_count = mutex_group->m_un.m_mutex_count;
- mutex_group->FinalizeMutexArray(Mutex_count);
- const size_t anyting_not_zero = 2 * sizeof(size_t);
- const dxtemplateMutexGroup<tThreadMutex> *const dummy_group = (dxtemplateMutexGroup<tThreadMutex> *)anyting_not_zero;
- const size_t size_requited = ((size_t)(&dummy_group->m_Mutex_array) - (size_t)dummy_group) + Mutex_count * sizeof(tThreadMutex);
- dFree((void *)mutex_group, size_requited);
- }
- }
- template<class tThreadMutex>
- bool dxtemplateMutexGroup<tThreadMutex>::InitializeMutexArray(dmutexindex_t Mutex_count)
- {
- bool any_fault = false;
- dmutexindex_t mutex_index = 0;
- for (; mutex_index != Mutex_count; ++mutex_index)
- {
- tThreadMutex *mutex_storage = m_Mutex_array + mutex_index;
- new(mutex_storage) tThreadMutex;
- if (!mutex_storage->InitializeObject())
- {
- mutex_storage->tThreadMutex::~tThreadMutex();
- any_fault = true;
- break;
- }
- }
- if (any_fault)
- {
- FinalizeMutexArray(mutex_index);
- }
- bool init_result = !any_fault;
- return init_result;
- }
- template<class tThreadMutex>
- void dxtemplateMutexGroup<tThreadMutex>::FinalizeMutexArray(dmutexindex_t Mutex_count)
- {
- for (dmutexindex_t mutex_index = 0; mutex_index != Mutex_count; ++mutex_index)
- {
- tThreadMutex *mutex_storage = m_Mutex_array + mutex_index;
- mutex_storage->tThreadMutex::~tThreadMutex();
- }
- }
- /************************************************************************/
- /* Implementation of dxtemplateJobListContainer */
- /************************************************************************/
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- dxThreadedJobInfo *dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::ReleaseAJobAndPickNextPendingOne(
- dxThreadedJobInfo *job_to_release, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr, bool &out_last_job_flag)
- {
- if (job_to_release != NULL)
- {
- ReleaseAJob(job_to_release, job_result, wait_signal_proc_ptr);
- }
- dxMutexLockHelper list_access(m_list_access_lock);
- dxThreadedJobInfo *picked_job = PickNextPendingJob(out_last_job_flag);
- return picked_job;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- dxThreadedJobInfo *dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::PickNextPendingJob(
- bool &out_last_job_flag)
- {
- dxThreadedJobInfo *current_job = m_job_list;
- bool last_job_flag = false;
- while (current_job != NULL)
- {
- if (current_job->m_dependencies_count == 0)
- {
- // It is OK to assign in unsafe manner - dependencies count should not be changed
- // after the job has become ready for execution
- current_job->m_dependencies_count = 1;
- last_job_flag = current_job->m_next_job == NULL;
- RemoveJobInfoFromList(current_job);
- break;
- }
- current_job = current_job->m_next_job;
- }
- out_last_job_flag = last_job_flag;
- return current_job;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::ReleaseAJob(
- dxThreadedJobInfo *job_instance, bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr)
- {
- dxThreadedJobInfo *current_job = job_instance;
- if (!job_result)
- {
- // Accumulate call fault (be careful to not reset it!!!)
- current_job->m_call_fault = 1;
- }
- bool job_dequeued = true;
- dIASSERT(current_job->m_prev_job_next_ptr == NULL);
- while (true)
- {
- dIASSERT(current_job->m_dependencies_count != 0);
- ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(current_job, -1);
- if (new_dependencies_count != 0 || !job_dequeued)
- {
- break;
- }
- void *job_call_wait = current_job->m_call_wait;
- if (job_call_wait != NULL)
- {
- wait_signal_proc_ptr(job_call_wait);
- }
- int call_fault = current_job->m_call_fault;
- if (current_job->m_fault_accumulator_ptr)
- {
- *current_job->m_fault_accumulator_ptr = call_fault;
- }
- dxThreadedJobInfo *dependent_job = current_job->m_dependent_job;
- ReleaseJobInfoIntoPool(current_job);
- if (dependent_job == NULL)
- {
- break;
- }
- if (call_fault)
- {
- // Accumulate call fault (be careful to not reset it!!!)
- dependent_job->m_call_fault = 1;
- }
- current_job = dependent_job;
- job_dequeued = dependent_job->m_prev_job_next_ptr == NULL;
- }
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- dxThreadedJobInfo *dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::AllocateJobInfoFromPool()
- {
- // No locking is necessary
- dxThreadedJobInfo *job_instance = ExtractJobInfoFromPoolOrAllocate();
- return job_instance;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::QueueJobForProcessing(dxThreadedJobInfo *job_instance)
- {
- dxMutexLockHelper list_access(m_list_access_lock);
- InsertJobInfoIntoListHead(job_instance);
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::AlterJobProcessingDependencies(dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change,
- bool &out_job_has_become_ready)
- {
- // Dependencies should not be changed when job has already become ready for execution
- dIASSERT(job_instance->m_dependencies_count != 0);
- // It's OK that access is not atomic - that is to be handled by external logic
- dIASSERT(dependencies_count_change < 0 ? (job_instance->m_dependencies_count >= (ddependencycount_t)(-dependencies_count_change)) : ((ddependencycount_t)(-(ddependencychange_t)job_instance->m_dependencies_count) > (ddependencycount_t)dependencies_count_change));
- ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(job_instance, dependencies_count_change);
- out_job_has_become_ready = new_dependencies_count == 0;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- ddependencycount_t dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::SmartAddJobDependenciesCount(
- dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change)
- {
- ddependencycount_t new_dependencies_count = tAtomicsProvider::template AddValueToTarget<sizeof(ddependencycount_t)>((volatile void *)&job_instance->m_dependencies_count, dependencies_count_change) + dependencies_count_change;
- return new_dependencies_count;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::InsertJobInfoIntoListHead(
- dxThreadedJobInfo *job_instance)
- {
- dxThreadedJobInfo *job_list_head = m_job_list;
- job_instance->m_next_job = job_list_head;
- if (job_list_head != NULL)
- {
- job_list_head->m_prev_job_next_ptr = &job_instance->m_next_job;
- }
- job_instance->m_prev_job_next_ptr = &m_job_list;
- m_job_list = job_instance;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::RemoveJobInfoFromList(
- dxThreadedJobInfo *job_instance)
- {
- if (job_instance->m_next_job)
- {
- job_instance->m_next_job->m_prev_job_next_ptr = job_instance->m_prev_job_next_ptr;
- }
- *job_instance->m_prev_job_next_ptr = job_instance->m_next_job;
- // Assign NULL to m_prev_job_next_ptr as an indicator that instance has been dequeued
- job_instance->m_prev_job_next_ptr = NULL;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- dxThreadedJobInfo *dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::ExtractJobInfoFromPoolOrAllocate()
- {
- dxThreadedJobInfo *result_info;
- bool waited_lull = false;
- m_info_wait_lull.RegisterToLull();
- while (true)
- {
- dxThreadedJobInfo *raw_head_info = (dxThreadedJobInfo *)m_info_pool;
- if (raw_head_info == NULL)
- {
- result_info = new dxThreadedJobInfo();
- if (result_info != NULL)
- {
- break;
- }
- m_info_wait_lull.WaitForLullAlarm();
- waited_lull = true;
- }
- // Extraction must be locked so that other thread does not "steal" head info,
- // use it and then reinsert back with a different "next"
- dxMutexLockHelper pool_access(m_pool_access_lock);
- dxThreadedJobInfo *head_info = (dxThreadedJobInfo *)m_info_pool; // Head info must be re-read after mutex had been locked
- if (head_info != NULL)
- {
- dxThreadedJobInfo *next_info = head_info->m_next_job;
- if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)head_info, (atomicptr_t)next_info))
- {
- result_info = head_info;
- break;
- }
- }
- }
- m_info_wait_lull.UnregisterFromLull();
- if (waited_lull)
- {
- // It is necessary to re-signal lull alarm if current thread was waiting as
- // there might be other threads waiting which might have not received alarm signal.
- m_info_wait_lull.SignalLullAlarmIfAnyRegistrants();
- }
- return result_info;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::ReleaseJobInfoIntoPool(
- dxThreadedJobInfo *job_instance)
- {
- while (true)
- {
- dxThreadedJobInfo *next_info = (dxThreadedJobInfo *)m_info_pool;
- job_instance->m_next_job = next_info;
- if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)next_info, (atomicptr_t)job_instance))
- {
- break;
- }
- }
- m_info_wait_lull.SignalLullAlarmIfAnyRegistrants();
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- void dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::FreeJobInfoPoolInfos()
- {
- dxThreadedJobInfo *current_info = (dxThreadedJobInfo *)m_info_pool;
- while (current_info != NULL)
- {
- dxThreadedJobInfo *info_save = current_info;
- current_info = current_info->m_next_job;
- delete info_save;
- }
- m_info_pool = (atomicptr_t)NULL;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- bool dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::EnsureNumberOfJobInfosIsPreallocated(ddependencycount_t required_info_count)
- {
- bool result = required_info_count <= m_info_count_known_to_be_preallocated
- || DoPreallocateJobInfos(required_info_count);
- return result;
- }
- template<class tThreadLull, class tThreadMutex, class tAtomicsProvider>
- bool dxtemplateJobListContainer<tThreadLull, tThreadMutex, tAtomicsProvider>::DoPreallocateJobInfos(ddependencycount_t required_info_count)
- {
- dIASSERT(required_info_count > m_info_count_known_to_be_preallocated); // Also ensures required_info_count > 0
- bool allocation_failure = false;
- dxThreadedJobInfo *info_pool = (dxThreadedJobInfo *)m_info_pool;
- ddependencycount_t info_index = 0;
- for (dxThreadedJobInfo **current_info_ptr = &info_pool; ; )
- {
- dxThreadedJobInfo *current_info = *current_info_ptr;
- if (current_info == NULL)
- {
- current_info = new dxThreadedJobInfo(NULL);
- if (current_info == NULL)
- {
- allocation_failure = true;
- break;
- }
- *current_info_ptr = current_info;
- }
- if (++info_index == required_info_count)
- {
- m_info_count_known_to_be_preallocated = info_index;
- break;
- }
- current_info_ptr = ¤t_info->m_next_job;
- }
- // Make sure m_info_pool was not changed
- dIASSERT(m_info_pool == NULL || m_info_pool == (atomicptr_t)info_pool);
- m_info_pool = (atomicptr_t)info_pool;
- bool result = !allocation_failure;
- return result;
- }
- #if dBUILTIN_THREADING_IMPL_ENABLED
- /************************************************************************/
- /* Implementation of dxtemplateJobListThreadedHandler */
- /************************************************************************/
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ProcessActiveJobAddition()
- {
- ActivateAnIdleThread();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PrepareForWaitingAJobCompletion()
- {
- // Do nothing
- }
- template<class tThreadWakeup, class tJobListContainer>
- unsigned dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::RetrieveActiveThreadsCount()
- {
- return GetActiveThreadsCount();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/)
- {
- RegisterAsActiveThread();
- if (readiness_callback != NULL)
- {
- (*readiness_callback)(callback_context);
- }
- PerformJobProcessingUntilShutdown();
- UnregisterAsActiveThread();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingUntilShutdown()
- {
- while (true)
- {
- // It is expected that new jobs will not be queued any longer after shutdown had been requested
- if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown())
- {
- break;
- }
- PerformJobProcessingSession();
- // It is expected that new jobs will not be queued any longer after shutdown had been requested
- if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown())
- {
- break;
- }
- BlockAsIdleThread();
- }
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingSession()
- {
- dxThreadedJobInfo *current_job = NULL;
- bool job_result = false;
- while (true)
- {
- bool last_job_flag;
- current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, last_job_flag);
- if (!current_job)
- {
- break;
- }
- if (!last_job_flag)
- {
- ActivateAnIdleThread();
- }
- job_result = current_job->InvokeCallFunction();
- }
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::BlockAsIdleThread()
- {
- m_processing_wakeup.WaitWakeup(NULL);
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ActivateAnIdleThread()
- {
- m_processing_wakeup.WakeupAThread();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ShutdownProcessing()
- {
- m_shutdown_requested = true;
- m_processing_wakeup.WakeupAllThreads();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::CleanupForRestart()
- {
- m_shutdown_requested = false;
- m_processing_wakeup.ResetWakeup();
- }
- #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
- /************************************************************************/
- /* Implementation of dxtemplateJobListSelfHandler */
- /************************************************************************/
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::ProcessActiveJobAddition()
- {
- // Do nothing
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::PrepareForWaitingAJobCompletion()
- {
- PerformJobProcessingUntilExhaustion();
- }
- template<class tThreadWakeup, class tJobListContainer>
- unsigned dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::RetrieveActiveThreadsCount()
- {
- return 1U; // Self-Handling is always performed by a single thread
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/)
- {
- (void)readiness_callback; // unused
- (void)callback_context; // unused
- dIASSERT(false); // This method is not expected to be called for Self-Handler
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingUntilExhaustion()
- {
- PerformJobProcessingSession();
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingSession()
- {
- dxThreadedJobInfo *current_job = NULL;
- bool job_result = false;
- while (true)
- {
- bool dummy_last_job_flag;
- current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, dummy_last_job_flag);
- if (!current_job)
- {
- break;
- }
- job_result = current_job->InvokeCallFunction();
- }
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::ShutdownProcessing()
- {
- // Do nothing
- }
- template<class tThreadWakeup, class tJobListContainer>
- void dxtemplateJobListSelfHandler<tThreadWakeup, tJobListContainer>::CleanupForRestart()
- {
- // Do nothing
- }
- /************************************************************************/
- /* Implementation of dxtemplateThreadingImplementation */
- /************************************************************************/
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::FreeInstance()
- {
- delete this;
- }
- template<class tJobListContainer, class tJobListHandler>
- dIMutexGroup *dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::AllocMutexGroup(dmutexindex_t Mutex_count)
- {
- dxMutexGroup *mutex_group = dxMutexGroup::AllocateInstance(Mutex_count);
- return (dIMutexGroup *)mutex_group;
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::FreeMutexGroup(dIMutexGroup *mutex_group)
- {
- dxMutexGroup::FreeInstance((dxMutexGroup *)mutex_group);
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index)
- {
- ((dxMutexGroup *)mutex_group)->LockMutex(mutex_index);
- }
- // template<class tJobListContainer, class tJobListHandler>
- // bool dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::TryLockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index)
- // {
- // return ((dxMutexGroup *)mutex_group)->TryLockMutex(mutex_index);
- // }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index)
- {
- ((dxMutexGroup *)mutex_group)->UnlockMutex(mutex_index);
- }
- template<class tJobListContainer, class tJobListHandler>
- dxICallWait *dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::AllocACallWait()
- {
- dxCallWait *call_wait = new dxCallWait();
- if (call_wait != NULL && !call_wait->InitializeObject())
- {
- delete call_wait;
- call_wait = NULL;
- }
- return (dxICallWait *)call_wait;
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::ResetACallWait(dxICallWait *call_wait)
- {
- ((dxCallWait *)call_wait)->ResetTheWait();
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::FreeACallWait(dxICallWait *call_wait)
- {
- delete ((dxCallWait *)call_wait);
- }
- template<class tJobListContainer, class tJobListHandler>
- bool dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate)
- {
- // No multithreading protection here!
- // Resources are to be preallocated before jobs start to be scheduled
- // as otherwise there is no way to implement the preallocation.
- bool result = m_list_container.EnsureNumberOfJobInfosIsPreallocated(max_simultaneous_calls_estimate);
- return result;
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::ScheduleNewJob(
- int *fault_accumulator_ptr/*=NULL*/,
- dCallReleaseeID *out_post_releasee_ptr/*=NULL*/, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee/*=NULL*/,
- dxICallWait *call_wait/*=NULL*/,
- dThreadedCallFunction *call_func, void *call_context, dcallindex_t instance_index)
- {
- dxThreadedJobInfo *new_job = m_list_container.AllocateJobInfoFromPool();
- dIASSERT(new_job != NULL);
- new_job->AssignJobData(dependencies_count, dMAKE_RELEASEE_JOBINSTANCE(dependent_releasee), (dxCallWait *)call_wait, fault_accumulator_ptr, call_func, call_context, instance_index);
- if (out_post_releasee_ptr != NULL)
- {
- *out_post_releasee_ptr = dMAKE_JOBINSTANCE_RELEASEE(new_job);
- }
- m_list_container.QueueJobForProcessing(new_job);
- if (dependencies_count == 0)
- {
- m_list_handler.ProcessActiveJobAddition();
- }
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::AlterJobDependenciesCount(
- dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change)
- {
- dIASSERT(dependencies_count_change != 0);
- dxThreadedJobInfo *job_instance = dMAKE_RELEASEE_JOBINSTANCE(target_releasee);
- bool job_has_become_ready;
- m_list_container.AlterJobProcessingDependencies(job_instance, dependencies_count_change, job_has_become_ready);
- if (job_has_become_ready)
- {
- m_list_handler.ProcessActiveJobAddition();
- }
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::WaitJobCompletion(
- int *out_wait_status_ptr/*=NULL*/,
- dxICallWait *call_wait, const dThreadedWaitTime *timeout_time_ptr/*=NULL*/)
- {
- dIASSERT(call_wait != NULL);
- m_list_handler.PrepareForWaitingAJobCompletion();
- bool wait_status = ((dxCallWait *)call_wait)->PerformWaiting(timeout_time_ptr);
- dIASSERT(timeout_time_ptr != NULL || wait_status);
- if (out_wait_status_ptr)
- {
- *out_wait_status_ptr = wait_status;
- }
- }
- template<class tJobListContainer, class tJobListHandler>
- unsigned dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::RetrieveActiveThreadsCount()
- {
- return m_list_handler.RetrieveActiveThreadsCount();
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback/*=NULL*/, void *callback_context/*=NULL*/)
- {
- m_list_handler.StickToJobsProcessing(readiness_callback, callback_context);
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::ShutdownProcessing()
- {
- m_list_handler.ShutdownProcessing();
- }
- template<class tJobListContainer, class tJobListHandler>
- void dxtemplateThreadingImplementation<tJobListContainer, tJobListHandler>::CleanupForRestart()
- {
- m_list_handler.CleanupForRestart();
- }
- #endif // #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_
|