33 #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_
34 #define _ODE_THREADING_IMPL_TEMPLATES_H_
37 #include <ode/common.h>
38 #include <ode/memory.h>
40 #include <ode/threading.h>
47 #define dMAKE_JOBINSTANCE_RELEASEE(job_instance) ((dCallReleaseeID)(job_instance))
48 #define dMAKE_RELEASEE_JOBINSTANCE(releasee) ((dxThreadedJobInfo *)(releasee))
51 template <
class tThreadMutex>
63 bool InitializeMutexArray(dmutexindex_t Mutex_count);
64 void FinalizeMutexArray(dmutexindex_t Mutex_count);
67 void LockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].LockMutex(); }
68 bool TryLockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count);
return m_Mutex_array[mutex_index].TryLockMutex(); }
69 void UnlockMutex(dmutexindex_t mutex_index) { dIASSERT(mutex_index < m_un.m_mutex_count); m_Mutex_array[mutex_index].UnlockMutex(); }
74 dmutexindex_t m_mutex_count;
75 unsigned long m_reserved_for_allignment[2];
79 tThreadMutex m_Mutex_array[1];
82 template<
class tThreadWakeup>
90 bool InitializeObject() {
return DoInitializeObject(); }
93 bool DoInitializeObject() {
return m_wait_wakeup.InitializeObject(); }
94 void DoFinalizeObject() { }
100 void ResetTheWait() { m_wait_wakeup.ResetWakeup(); }
101 void SignalTheWait() { m_wait_wakeup.WakeupAllThreads(); }
102 bool PerformWaiting(
const dThreadedWaitTime *timeout_time_ptr) {
return m_wait_wakeup.WaitWakeup(timeout_time_ptr); }
105 static void AbstractSignalTheWait(
void *wait_wakeup_ptr) { ((dxCallWait *)wait_wakeup_ptr)->SignalTheWait(); }
108 tThreadWakeup m_wait_wakeup;
112 #if dBUILTIN_THREADING_IMPL_ENABLED
114 template<
class tThreadWakeup,
class tAtomicsProv
ider, const
bool tatomic_test_required>
115 class dxtemplateThreadedLull
118 dxtemplateThreadedLull(): m_registrant_count(0), m_alarm_wakeup() {}
119 ~dxtemplateThreadedLull() { dIASSERT(m_registrant_count == 0); DoFinalizeObject(); }
121 bool InitializeObject() {
return DoInitializeObject(); }
124 bool DoInitializeObject() {
return m_alarm_wakeup.InitializeObject(); }
125 void DoFinalizeObject() { }
128 typedef typename tAtomicsProvider::atomicord_t atomicord_t;
131 void RegisterToLull() { tAtomicsProvider::IncrementTargetNoRet(&m_registrant_count); }
132 void WaitForLullAlarm() { dIASSERT(m_registrant_count != 0); m_alarm_wakeup.WaitWakeup(NULL); }
133 void UnregisterFromLull() { tAtomicsProvider::DecrementTargetNoRet(&m_registrant_count); }
135 void SignalLullAlarmIfAnyRegistrants()
137 if (tatomic_test_required ? (tAtomicsProvider::QueryTargetValue(&m_registrant_count) != 0) : (m_registrant_count != 0))
139 m_alarm_wakeup.WakeupAThread();
144 atomicord_t m_registrant_count;
145 tThreadWakeup m_alarm_wakeup;
149 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
158 void AssignJobData(ddependencycount_t dependencies_count,
dxThreadedJobInfo *dependent_job,
void *call_wait,
159 int *fault_accumulator_ptr, dThreadedCallFunction *call_function,
void *call_context, dcallindex_t call_index)
161 m_dependencies_count = dependencies_count;
162 m_dependent_job = dependent_job;
163 m_call_wait = call_wait;
164 m_fault_accumulator_ptr = fault_accumulator_ptr;
167 m_call_function = call_function;
168 m_call_context = call_context;
169 m_call_index = call_index;
172 bool InvokeCallFunction()
174 int call_result = m_call_function(m_call_context, m_call_index, dMAKE_JOBINSTANCE_RELEASEE(
this));
175 return call_result != 0;
181 ddependencycount_t m_dependencies_count;
184 int *m_fault_accumulator_ptr;
187 dThreadedCallFunction *m_call_function;
188 void *m_call_context;
189 dcallindex_t m_call_index;
193 template<
class tThreadMutex>
200 void LockMutex() { dIASSERT(!m_lock_indicator_flag); m_mutex_instance.LockMutex(); m_lock_indicator_flag =
true; }
201 void UnlockMutex() { dIASSERT(m_lock_indicator_flag); m_mutex_instance.UnlockMutex(); m_lock_indicator_flag =
false; }
204 tThreadMutex &m_mutex_instance;
205 bool m_lock_indicator_flag;
208 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
214 m_info_pool((atomicptr_t)NULL),
215 m_pool_access_lock(),
216 m_list_access_lock(),
218 m_info_count_known_to_be_preallocated(0)
224 dIASSERT(m_job_list == NULL);
226 FreeJobInfoPoolInfos();
230 bool InitializeObject() {
return DoInitializeObject(); }
233 bool DoInitializeObject() {
return m_pool_access_lock.InitializeObject() && m_list_access_lock.InitializeObject() && m_info_wait_lull.InitializeObject(); }
234 void DoFinalizeObject() { }
237 typedef tAtomicsProvider dxAtomicsProvider;
238 typedef typename tAtomicsProvider::atomicord_t atomicord_t;
239 typedef typename tAtomicsProvider::atomicptr_t atomicptr_t;
240 typedef tThreadMutex dxThreadMutex;
242 typedef void dWaitSignallingFunction(
void *job_call_wait);
246 dxThreadedJobInfo *job_to_release,
bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr,
247 bool &out_last_job_flag);
251 void ReleaseAJob(
dxThreadedJobInfo *job_instance,
bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr);
257 void AlterJobProcessingDependencies(
dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change,
258 bool &out_job_has_become_ready);
261 inline ddependencycount_t SmartAddJobDependenciesCount(
dxThreadedJobInfo *job_instance, ddependencychange_t dependencies_count_change);
270 void FreeJobInfoPoolInfos();
273 bool EnsureNumberOfJobInfosIsPreallocated(ddependencycount_t required_info_count);
276 bool DoPreallocateJobInfos(ddependencycount_t required_info_count);
279 bool IsJobListReadyForShutdown()
const {
return m_job_list == NULL; }
283 volatile atomicptr_t m_info_pool;
284 tThreadMutex m_pool_access_lock;
285 tThreadMutex m_list_access_lock;
286 tThreadLull m_info_wait_lull;
287 ddependencycount_t m_info_count_known_to_be_preallocated;
291 typedef void (dxThreadReadyToServeCallback)(
void *callback_context);
294 #if dBUILTIN_THREADING_IMPL_ENABLED
296 template<
class tThreadWakeup,
class tJobListContainer>
297 class dxtemplateJobListThreadedHandler
300 dxtemplateJobListThreadedHandler(tJobListContainer *list_container_ptr):
301 m_job_list_ptr(list_container_ptr),
302 m_processing_wakeup(),
303 m_active_thread_count(0),
304 m_shutdown_requested(0)
308 ~dxtemplateJobListThreadedHandler()
310 dIASSERT(m_active_thread_count == 0);
315 bool InitializeObject() {
return DoInitializeObject(); }
318 bool DoInitializeObject() {
return m_processing_wakeup.InitializeObject(); }
319 void DoFinalizeObject() { }
325 inline void ProcessActiveJobAddition();
326 inline void PrepareForWaitingAJobCompletion();
329 inline unsigned RetrieveActiveThreadsCount();
330 inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback,
void *callback_context);
333 void PerformJobProcessingUntilShutdown();
334 void PerformJobProcessingSession();
336 void BlockAsIdleThread();
337 void ActivateAnIdleThread();
340 inline void ShutdownProcessing();
341 inline void CleanupForRestart();
344 bool IsShutdownRequested()
const {
return m_shutdown_requested != 0; }
347 typedef typename tJobListContainer::dxAtomicsProvider dxAtomicsProvider;
348 typedef typename tJobListContainer::atomicord_t atomicord_t;
350 atomicord_t GetActiveThreadsCount()
const {
return m_active_thread_count; }
351 void RegisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget<sizeof(atomicord_t)>((
volatile void *)&m_active_thread_count, 1); }
352 void UnregisterAsActiveThread() { dxAtomicsProvider::template AddValueToTarget<sizeof(atomicord_t)>((
volatile void *)&m_active_thread_count, -1); }
355 tJobListContainer *m_job_list_ptr;
356 tThreadWakeup m_processing_wakeup;
357 volatile atomicord_t m_active_thread_count;
358 int m_shutdown_requested;
362 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
365 template<
class tThreadWakeup,
class tJobListContainer>
370 m_job_list_ptr(list_container_ptr)
379 bool InitializeObject() {
return true; }
385 inline void ProcessActiveJobAddition();
386 inline void PrepareForWaitingAJobCompletion();
389 inline unsigned RetrieveActiveThreadsCount();
390 inline void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback,
void *callback_context);
393 void PerformJobProcessingUntilExhaustion();
394 void PerformJobProcessingSession();
397 inline void ShutdownProcessing();
398 inline void CleanupForRestart();
401 tJobListContainer *m_job_list_ptr;
411 virtual void FreeInstance() = 0;
414 virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count) = 0;
415 virtual void FreeMutexGroup(dIMutexGroup *mutex_group) = 0;
416 virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0;
418 virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index) = 0;
421 virtual dxICallWait *AllocACallWait() = 0;
422 virtual void ResetACallWait(dxICallWait *call_wait) = 0;
423 virtual void FreeACallWait(dxICallWait *call_wait) = 0;
426 virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate) = 0;
427 virtual void ScheduleNewJob(
int *fault_accumulator_ptr,
428 dCallReleaseeID *out_post_releasee_ptr, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee,
429 dxICallWait *call_wait,
430 dThreadedCallFunction *call_func,
void *call_context, dcallindex_t instance_index) = 0;
431 virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change) = 0;
432 virtual void WaitJobCompletion(
int *out_wait_status_ptr,
436 virtual unsigned RetrieveActiveThreadsCount() = 0;
437 virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback,
void *callback_context) = 0;
438 virtual void ShutdownProcessing() = 0;
439 virtual void CleanupForRestart() = 0;
443 template<
class tJobListContainer,
class tJobListHandler>
452 m_list_handler(&m_list_container)
461 bool InitializeObject() {
return DoInitializeObject(); }
464 bool DoInitializeObject() {
return m_list_container.InitializeObject() && m_list_handler.InitializeObject(); }
465 void DoFinalizeObject() { }
468 virtual void FreeInstance();
472 typedef typename tJobListHandler::dxCallWait dxCallWait;
475 virtual dIMutexGroup *AllocMutexGroup(dmutexindex_t Mutex_count);
476 virtual void FreeMutexGroup(dIMutexGroup *mutex_group);
477 virtual void LockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index);
479 virtual void UnlockMutexGroupMutex(dIMutexGroup *mutex_group, dmutexindex_t mutex_index);
482 virtual dxICallWait *AllocACallWait();
483 virtual void ResetACallWait(dxICallWait *call_wait);
484 virtual void FreeACallWait(dxICallWait *call_wait);
487 virtual bool PreallocateJobInfos(ddependencycount_t max_simultaneous_calls_estimate);
488 virtual void ScheduleNewJob(
int *fault_accumulator_ptr,
489 dCallReleaseeID *out_post_releasee_ptr, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee,
490 dxICallWait *call_wait,
491 dThreadedCallFunction *call_func,
void *call_context, dcallindex_t instance_index);
492 virtual void AlterJobDependenciesCount(dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change);
493 virtual void WaitJobCompletion(
int *out_wait_status_ptr,
497 virtual unsigned RetrieveActiveThreadsCount();
498 virtual void StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback,
void *callback_context);
499 virtual void ShutdownProcessing();
500 virtual void CleanupForRestart();
503 tJobListContainer m_list_container;
504 tJobListHandler m_list_handler;
512 template<
class tThreadMutex>
515 dAASSERT(Mutex_count != 0);
518 const size_t size_requited = ((size_t)(&dummy_group->m_Mutex_array) - (size_t)dummy_group) + Mutex_count *
sizeof(tThreadMutex);
521 if (mutex_group != NULL)
523 mutex_group->m_un.m_mutex_count = Mutex_count;
525 if (!mutex_group->InitializeMutexArray(Mutex_count))
527 dFree((
void *)mutex_group, size_requited);
535 template<
class tThreadMutex>
538 if (mutex_group != NULL)
540 dmutexindex_t Mutex_count = mutex_group->m_un.m_mutex_count;
541 mutex_group->FinalizeMutexArray(Mutex_count);
543 const size_t anyting_not_zero = 2 *
sizeof(size_t);
545 const size_t size_requited = ((size_t)(&dummy_group->m_Mutex_array) - (size_t)dummy_group) + Mutex_count *
sizeof(tThreadMutex);
546 dFree((
void *)mutex_group, size_requited);
550 template<
class tThreadMutex>
553 bool any_fault =
false;
555 dmutexindex_t mutex_index = 0;
556 for (; mutex_index != Mutex_count; ++mutex_index)
558 tThreadMutex *mutex_storage = m_Mutex_array + mutex_index;
560 new(mutex_storage) tThreadMutex;
562 if (!mutex_storage->InitializeObject())
564 mutex_storage->tThreadMutex::~tThreadMutex();
573 FinalizeMutexArray(mutex_index);
576 bool init_result = !any_fault;
580 template<
class tThreadMutex>
583 for (dmutexindex_t mutex_index = 0; mutex_index != Mutex_count; ++mutex_index)
585 tThreadMutex *mutex_storage = m_Mutex_array + mutex_index;
587 mutex_storage->tThreadMutex::~tThreadMutex();
595 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
597 dxThreadedJobInfo *job_to_release,
bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr,
bool &out_last_job_flag)
599 if (job_to_release != NULL)
601 ReleaseAJob(job_to_release, job_result, wait_signal_proc_ptr);
604 dxMutexLockHelper list_access(m_list_access_lock);
610 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
612 bool &out_last_job_flag)
615 bool last_job_flag =
false;
617 while (current_job != NULL)
619 if (current_job->m_dependencies_count == 0)
623 current_job->m_dependencies_count = 1;
624 last_job_flag = current_job->m_next_job == NULL;
626 RemoveJobInfoFromList(current_job);
630 current_job = current_job->m_next_job;
633 out_last_job_flag = last_job_flag;
637 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
639 dxThreadedJobInfo *job_instance,
bool job_result, dWaitSignallingFunction *wait_signal_proc_ptr)
646 current_job->m_call_fault = 1;
649 bool job_dequeued =
true;
650 dIASSERT(current_job->m_prev_job_next_ptr == NULL);
654 dIASSERT(current_job->m_dependencies_count != 0);
656 ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(current_job, -1);
658 if (new_dependencies_count != 0 || !job_dequeued)
663 void *job_call_wait = current_job->m_call_wait;
665 if (job_call_wait != NULL)
667 wait_signal_proc_ptr(job_call_wait);
670 int call_fault = current_job->m_call_fault;
672 if (current_job->m_fault_accumulator_ptr)
674 *current_job->m_fault_accumulator_ptr = call_fault;
678 ReleaseJobInfoIntoPool(current_job);
680 if (dependent_job == NULL)
688 dependent_job->m_call_fault = 1;
691 current_job = dependent_job;
692 job_dequeued = dependent_job->m_prev_job_next_ptr == NULL;
696 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
704 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
707 dxMutexLockHelper list_access(m_list_access_lock);
709 InsertJobInfoIntoListHead(job_instance);
713 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
715 bool &out_job_has_become_ready)
718 dIASSERT(job_instance->m_dependencies_count != 0);
720 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));
722 ddependencycount_t new_dependencies_count = SmartAddJobDependenciesCount(job_instance, dependencies_count_change);
723 out_job_has_become_ready = new_dependencies_count == 0;
727 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
731 ddependencycount_t new_dependencies_count = tAtomicsProvider::template AddValueToTarget<sizeof(ddependencycount_t)>((
volatile void *)&job_instance->m_dependencies_count, dependencies_count_change) + dependencies_count_change;
732 return new_dependencies_count;
736 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
741 job_instance->m_next_job = job_list_head;
743 if (job_list_head != NULL)
745 job_list_head->m_prev_job_next_ptr = &job_instance->m_next_job;
748 job_instance->m_prev_job_next_ptr = &m_job_list;
749 m_job_list = job_instance;
752 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
756 if (job_instance->m_next_job)
758 job_instance->m_next_job->m_prev_job_next_ptr = job_instance->m_prev_job_next_ptr;
761 *job_instance->m_prev_job_next_ptr = job_instance->m_next_job;
763 job_instance->m_prev_job_next_ptr = NULL;
766 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
771 bool waited_lull =
false;
772 m_info_wait_lull.RegisterToLull();
778 if (raw_head_info == NULL)
782 if (result_info != NULL)
787 m_info_wait_lull.WaitForLullAlarm();
793 dxMutexLockHelper pool_access(m_pool_access_lock);
797 if (head_info != NULL)
800 if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)head_info, (atomicptr_t)next_info))
802 result_info = head_info;
808 m_info_wait_lull.UnregisterFromLull();
814 m_info_wait_lull.SignalLullAlarmIfAnyRegistrants();
820 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
827 job_instance->m_next_job = next_info;
829 if (tAtomicsProvider::CompareExchangeTargetPtr(&m_info_pool, (atomicptr_t)next_info, (atomicptr_t)job_instance))
835 m_info_wait_lull.SignalLullAlarmIfAnyRegistrants();
838 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
843 while (current_info != NULL)
846 current_info = current_info->m_next_job;
851 m_info_pool = (atomicptr_t)NULL;
854 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
857 bool result = required_info_count <= m_info_count_known_to_be_preallocated
858 || DoPreallocateJobInfos(required_info_count);
862 template<
class tThreadLull,
class tThreadMutex,
class tAtomicsProv
ider>
865 dIASSERT(required_info_count > m_info_count_known_to_be_preallocated);
867 bool allocation_failure =
false;
871 ddependencycount_t info_index = 0;
876 if (current_info == NULL)
880 if (current_info == NULL)
882 allocation_failure =
true;
886 *current_info_ptr = current_info;
889 if (++info_index == required_info_count)
891 m_info_count_known_to_be_preallocated = info_index;
895 current_info_ptr = ¤t_info->m_next_job;
899 dIASSERT(m_info_pool == NULL || m_info_pool == (atomicptr_t)info_pool);
901 m_info_pool = (atomicptr_t)info_pool;
903 bool result = !allocation_failure;
908 #if dBUILTIN_THREADING_IMPL_ENABLED
914 template<
class tThreadWakeup,
class tJobListContainer>
915 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ProcessActiveJobAddition()
917 ActivateAnIdleThread();
920 template<
class tThreadWakeup,
class tJobListContainer>
921 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PrepareForWaitingAJobCompletion()
926 template<
class tThreadWakeup,
class tJobListContainer>
927 unsigned dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::RetrieveActiveThreadsCount()
929 return GetActiveThreadsCount();
932 template<
class tThreadWakeup,
class tJobListContainer>
933 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::StickToJobsProcessing(dxThreadReadyToServeCallback *readiness_callback,
void *callback_context)
935 RegisterAsActiveThread();
937 if (readiness_callback != NULL)
939 (*readiness_callback)(callback_context);
942 PerformJobProcessingUntilShutdown();
944 UnregisterAsActiveThread();
948 template<
class tThreadWakeup,
class tJobListContainer>
949 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingUntilShutdown()
954 if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown())
959 PerformJobProcessingSession();
962 if (IsShutdownRequested() && m_job_list_ptr->IsJobListReadyForShutdown())
971 template<
class tThreadWakeup,
class tJobListContainer>
972 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::PerformJobProcessingSession()
975 bool job_result =
false;
980 current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, last_job_flag);
989 ActivateAnIdleThread();
992 job_result = current_job->InvokeCallFunction();
997 template<
class tThreadWakeup,
class tJobListContainer>
998 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::BlockAsIdleThread()
1000 m_processing_wakeup.WaitWakeup(NULL);
1003 template<
class tThreadWakeup,
class tJobListContainer>
1004 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ActivateAnIdleThread()
1006 m_processing_wakeup.WakeupAThread();
1010 template<
class tThreadWakeup,
class tJobListContainer>
1011 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::ShutdownProcessing()
1013 m_shutdown_requested =
true;
1014 m_processing_wakeup.WakeupAllThreads();
1017 template<
class tThreadWakeup,
class tJobListContainer>
1018 void dxtemplateJobListThreadedHandler<tThreadWakeup, tJobListContainer>::CleanupForRestart()
1020 m_shutdown_requested =
false;
1021 m_processing_wakeup.ResetWakeup();
1025 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
1032 template<
class tThreadWakeup,
class tJobListContainer>
1038 template<
class tThreadWakeup,
class tJobListContainer>
1041 PerformJobProcessingUntilExhaustion();
1045 template<
class tThreadWakeup,
class tJobListContainer>
1051 template<
class tThreadWakeup,
class tJobListContainer>
1058 template<
class tThreadWakeup,
class tJobListContainer>
1061 PerformJobProcessingSession();
1064 template<
class tThreadWakeup,
class tJobListContainer>
1068 bool job_result =
false;
1072 bool dummy_last_job_flag;
1073 current_job = m_job_list_ptr->ReleaseAJobAndPickNextPendingOne(current_job, job_result, &dxCallWait::AbstractSignalTheWait, dummy_last_job_flag);
1080 job_result = current_job->InvokeCallFunction();
1084 template<
class tThreadWakeup,
class tJobListContainer>
1090 template<
class tThreadWakeup,
class tJobListContainer>
1101 template<
class tJobListContainer,
class tJobListHandler>
1108 template<
class tJobListContainer,
class tJobListHandler>
1111 dxMutexGroup *mutex_group = dxMutexGroup::AllocateInstance(Mutex_count);
1112 return (dIMutexGroup *)mutex_group;
1115 template<
class tJobListContainer,
class tJobListHandler>
1118 dxMutexGroup::FreeInstance((dxMutexGroup *)mutex_group);
1121 template<
class tJobListContainer,
class tJobListHandler>
1124 ((dxMutexGroup *)mutex_group)->LockMutex(mutex_index);
1133 template<
class tJobListContainer,
class tJobListHandler>
1136 ((dxMutexGroup *)mutex_group)->UnlockMutex(mutex_index);
1140 template<
class tJobListContainer,
class tJobListHandler>
1143 dxCallWait *call_wait =
new dxCallWait();
1145 if (call_wait != NULL && !call_wait->InitializeObject())
1151 return (dxICallWait *)call_wait;
1154 template<
class tJobListContainer,
class tJobListHandler>
1157 ((dxCallWait *)call_wait)->ResetTheWait();
1160 template<
class tJobListContainer,
class tJobListHandler>
1163 delete ((dxCallWait *)call_wait);
1167 template<
class tJobListContainer,
class tJobListHandler>
1173 bool result = m_list_container.EnsureNumberOfJobInfosIsPreallocated(max_simultaneous_calls_estimate);
1177 template<
class tJobListContainer,
class tJobListHandler>
1179 int *fault_accumulator_ptr,
1180 dCallReleaseeID *out_post_releasee_ptr, ddependencycount_t dependencies_count, dCallReleaseeID dependent_releasee,
1181 dxICallWait *call_wait,
1182 dThreadedCallFunction *call_func,
void *call_context, dcallindex_t instance_index)
1185 dIASSERT(new_job != NULL);
1187 new_job->AssignJobData(dependencies_count, dMAKE_RELEASEE_JOBINSTANCE(dependent_releasee), (dxCallWait *)call_wait, fault_accumulator_ptr, call_func, call_context, instance_index);
1189 if (out_post_releasee_ptr != NULL)
1191 *out_post_releasee_ptr = dMAKE_JOBINSTANCE_RELEASEE(new_job);
1194 m_list_container.QueueJobForProcessing(new_job);
1196 if (dependencies_count == 0)
1198 m_list_handler.ProcessActiveJobAddition();
1202 template<
class tJobListContainer,
class tJobListHandler>
1204 dCallReleaseeID target_releasee, ddependencychange_t dependencies_count_change)
1206 dIASSERT(dependencies_count_change != 0);
1210 bool job_has_become_ready;
1211 m_list_container.AlterJobProcessingDependencies(job_instance, dependencies_count_change, job_has_become_ready);
1213 if (job_has_become_ready)
1215 m_list_handler.ProcessActiveJobAddition();
1219 template<
class tJobListContainer,
class tJobListHandler>
1221 int *out_wait_status_ptr,
1224 dIASSERT(call_wait != NULL);
1226 m_list_handler.PrepareForWaitingAJobCompletion();
1228 bool wait_status = ((dxCallWait *)call_wait)->PerformWaiting(timeout_time_ptr);
1229 dIASSERT(timeout_time_ptr != NULL || wait_status);
1231 if (out_wait_status_ptr)
1233 *out_wait_status_ptr = wait_status;
1238 template<
class tJobListContainer,
class tJobListHandler>
1241 return m_list_handler.RetrieveActiveThreadsCount();
1244 template<
class tJobListContainer,
class tJobListHandler>
1247 m_list_handler.StickToJobsProcessing(readiness_callback, callback_context);
1250 template<
class tJobListContainer,
class tJobListHandler>
1253 m_list_handler.ShutdownProcessing();
1256 template<
class tJobListContainer,
class tJobListHandler>
1259 m_list_handler.CleanupForRestart();
1263 #endif // #ifndef _ODE_THREADING_IMPL_TEMPLATES_H_
Definition: ode/src/objects.h:57
Definition: threading_impl_templates.h:209
Definition: threading_impl_templates.h:194
Definition: threading_impl_templates.h:408
Definition: threading_impl_templates.h:152
Definition: threading_impl_templates.h:83
Definition: threading_impl_templates.h:444
Definition: threading_impl_templates.h:366
Definition: threading_impl_templates.h:52
Definition: threading.h:154