32 #ifndef _ODE_THREADING_IMPL_POSIX_H_
33 #define _ODE_THREADING_IMPL_POSIX_H_
36 #include <ode/common.h>
42 #include "threading_impl_templates.h"
43 #include "threading_fake_sync.h"
44 #include "threading_atomics_provs.h"
46 #if dBUILTIN_THREADING_IMPL_ENABLED
57 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
60 #if dBUILTIN_THREADING_IMPL_ENABLED
69 dxCondvarWakeup(): m_waiters_list(NULL), m_signaled_state(false), m_state_is_permanent(false), m_object_initialized(false) {}
70 ~dxCondvarWakeup() { DoFinalizeObject(); }
72 bool InitializeObject() {
return DoInitializeObject(); }
75 bool DoInitializeObject();
76 void DoFinalizeObject();
81 void WakeupAllThreads();
91 dxWaiterInfo(): m_signal_state(false) {}
93 dxWaiterInfo **m_prev_info_ptr;
94 dxWaiterInfo *m_next_info;
98 void RegisterWaiterInList(dxWaiterInfo *waiter_info);
99 void UnregisterWaiterFromList(dxWaiterInfo *waiter_info);
101 bool MarkSignaledFirstWaiter();
102 static bool MarkSignaledFirstWaiterMeaningful(dxWaiterInfo *first_waiter);
103 bool MarkSignaledAllWaiters();
104 static bool MarkSignaledAllWaitersMeaningful(dxWaiterInfo *first_waiter);
107 dxWaiterInfo *m_waiters_list;
108 bool m_signaled_state;
109 bool m_state_is_permanent;
110 bool m_object_initialized;
111 pthread_mutex_t m_wakeup_mutex;
112 pthread_cond_t m_wakeup_cond;
116 bool dxCondvarWakeup::DoInitializeObject()
118 dIASSERT(!m_object_initialized);
120 bool init_result =
false;
122 pthread_condattr_t cond_condattr;
123 bool mutex_initialized =
false, condattr_initialized =
false;
127 int mutex_result = pthread_mutex_init(&m_wakeup_mutex, NULL);
128 if (mutex_result != EOK)
130 errno = mutex_result;
134 mutex_initialized =
true;
136 int condattr_init_result = pthread_condattr_init(&cond_condattr);
137 if (condattr_init_result != EOK)
139 errno = condattr_init_result;
143 condattr_initialized =
true;
145 int condattr_clock_result = pthread_condattr_setclock(&cond_condattr, CLOCK_MONOTONIC);
146 if (condattr_clock_result != EOK)
148 errno = condattr_clock_result;
152 int cond_result = pthread_cond_init(&m_wakeup_cond, &cond_condattr);
153 if (cond_result != EOK)
159 pthread_condattr_destroy(&cond_condattr);
161 m_object_initialized =
true;
168 if (mutex_initialized)
170 if (condattr_initialized)
172 int condattr_destroy_result = pthread_condattr_destroy(&cond_condattr);
173 dICHECK(condattr_destroy_result == EOK || ((errno = condattr_destroy_result),
false));
176 int mutex_destroy_result = pthread_mutex_destroy(&m_wakeup_mutex);
177 dICHECK(mutex_destroy_result == EOK || ((errno = mutex_destroy_result),
false));
185 void dxCondvarWakeup::DoFinalizeObject()
187 if (m_object_initialized)
189 int cond_result = pthread_cond_destroy(&m_wakeup_cond);
190 dICHECK(cond_result == EOK || ((errno = cond_result),
false));
192 int mutex_result = pthread_mutex_destroy(&m_wakeup_mutex);
193 dICHECK(mutex_result == EOK || ((errno = mutex_result),
false));
195 m_object_initialized =
false;
200 void dxCondvarWakeup::ResetWakeup()
202 int lock_result = pthread_mutex_lock(&m_wakeup_mutex);
203 dICHECK(lock_result == EOK || ((errno = lock_result),
false));
205 m_signaled_state =
false;
206 m_state_is_permanent =
false;
208 int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex);
209 dICHECK(unlock_result == EOK || ((errno = unlock_result),
false));
212 void dxCondvarWakeup::WakeupAThread()
214 int lock_result = pthread_mutex_lock(&m_wakeup_mutex);
215 dICHECK(lock_result == EOK || ((errno = lock_result),
false));
217 dIASSERT(!m_state_is_permanent);
219 if (!m_signaled_state)
221 if (MarkSignaledFirstWaiter())
230 int broadcast_result = pthread_cond_broadcast(&m_wakeup_cond);
231 dICHECK(broadcast_result == EOK || ((errno = broadcast_result),
false));
235 m_signaled_state =
true;
239 int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex);
240 dICHECK(unlock_result == EOK || ((errno = unlock_result),
false));
243 void dxCondvarWakeup::WakeupAllThreads()
245 int lock_result = pthread_mutex_lock(&m_wakeup_mutex);
246 dICHECK(lock_result == EOK || ((errno = lock_result),
false));
248 m_state_is_permanent =
true;
250 if (!m_signaled_state)
252 m_signaled_state =
true;
254 if (MarkSignaledAllWaiters())
256 int broadcast_result = pthread_cond_broadcast(&m_wakeup_cond);
257 dICHECK(broadcast_result == EOK || ((errno = broadcast_result),
false));
261 int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex);
262 dICHECK(unlock_result == EOK || ((errno = unlock_result),
false));
270 int lock_result = pthread_mutex_lock(&m_wakeup_mutex);
271 dICHECK(lock_result == EOK || ((errno = lock_result),
false));
273 if (!m_signaled_state)
275 if (!timeout_time_ptr || timeout_time_ptr->wait_nsec != 0 || timeout_time_ptr->wait_sec != 0)
277 wait_result = BlockAsAWaiter(timeout_time_ptr);
286 m_signaled_state = m_state_is_permanent;
290 int unlock_result = pthread_mutex_unlock(&m_wakeup_mutex);
291 dICHECK(unlock_result == EOK || ((errno = unlock_result),
false));
298 bool wait_result =
false;
300 dxWaiterInfo waiter_info;
301 RegisterWaiterInList(&waiter_info);
303 timespec wakeup_time;
305 if (timeout_time_ptr != NULL)
307 timespec current_time;
309 int clock_result = clock_gettime(CLOCK_MONOTONIC, ¤t_time);
310 dICHECK(clock_result != -1);
312 time_t wakeup_sec = current_time.tv_sec + timeout_time_ptr->wait_sec;
313 unsigned long wakeup_nsec = current_time.tv_nsec + timeout_time_ptr->wait_nsec;
315 if (wakeup_nsec >= 1000000000)
317 wakeup_nsec -= 1000000000;
321 wakeup_time.tv_sec = wakeup_sec;
322 wakeup_time.tv_nsec = wakeup_nsec;
327 int cond_result = (timeout_time_ptr != NULL)
328 ? pthread_cond_timedwait(&m_wakeup_cond, &m_wakeup_mutex, &wakeup_time)
329 : pthread_cond_wait(&m_wakeup_cond, &m_wakeup_mutex);
330 dICHECK(cond_result == EOK || cond_result == ETIMEDOUT || ((errno = cond_result),
false));
332 if (waiter_info.m_signal_state)
338 if (cond_result == ETIMEDOUT)
340 dIASSERT(timeout_time_ptr != NULL);
345 UnregisterWaiterFromList(&waiter_info);
351 void dxCondvarWakeup::RegisterWaiterInList(dxWaiterInfo *waiter_info)
353 dxWaiterInfo *
const first_waiter = m_waiters_list;
355 if (first_waiter == NULL)
357 waiter_info->m_next_info = waiter_info;
358 waiter_info->m_prev_info_ptr = &waiter_info->m_next_info;
359 m_waiters_list = waiter_info;
363 waiter_info->m_next_info = first_waiter;
364 waiter_info->m_prev_info_ptr = first_waiter->m_prev_info_ptr;
365 *first_waiter->m_prev_info_ptr = waiter_info;
366 first_waiter->m_prev_info_ptr = &waiter_info->m_next_info;
370 void dxCondvarWakeup::UnregisterWaiterFromList(dxWaiterInfo *waiter_info)
372 dxWaiterInfo *next_info = waiter_info->m_next_info;
374 if (next_info == waiter_info)
376 m_waiters_list = NULL;
380 next_info->m_prev_info_ptr = waiter_info->m_prev_info_ptr;
381 *waiter_info->m_prev_info_ptr = next_info;
383 if (waiter_info == m_waiters_list)
385 m_waiters_list = next_info;
391 bool dxCondvarWakeup::MarkSignaledFirstWaiter()
393 bool waiter_found =
false;
395 dxWaiterInfo *
const first_waiter = m_waiters_list;
399 waiter_found = MarkSignaledFirstWaiterMeaningful(first_waiter);
405 bool dxCondvarWakeup::MarkSignaledFirstWaiterMeaningful(dxWaiterInfo *first_waiter)
407 bool waiter_found =
false;
409 dxWaiterInfo *current_waiter = first_waiter;
413 if (!current_waiter->m_signal_state)
415 current_waiter->m_signal_state =
true;
420 current_waiter = current_waiter->m_next_info;
421 if (current_waiter == first_waiter)
430 bool dxCondvarWakeup::MarkSignaledAllWaiters()
432 bool waiter_found =
false;
434 dxWaiterInfo *
const first_waiter = m_waiters_list;
438 waiter_found = MarkSignaledAllWaitersMeaningful(first_waiter);
444 bool dxCondvarWakeup::MarkSignaledAllWaitersMeaningful(dxWaiterInfo *first_waiter)
446 bool waiter_found =
false;
448 dxWaiterInfo *current_waiter = first_waiter;
452 if (!current_waiter->m_signal_state)
454 current_waiter->m_signal_state =
true;
458 current_waiter = current_waiter->m_next_info;
459 if (current_waiter == first_waiter)
476 dxMutexMutex(): m_mutex_allocated(false) {}
477 ~dxMutexMutex() { DoFinalizeObject(); }
479 bool InitializeObject() {
return DoInitializeObject(); }
482 bool DoInitializeObject();
483 void DoFinalizeObject();
491 pthread_mutex_t m_mutex_instance;
492 bool m_mutex_allocated;
496 bool dxMutexMutex::DoInitializeObject()
498 dIASSERT(!m_mutex_allocated);
500 bool init_result =
false;
504 int mutex_result = pthread_mutex_init(&m_mutex_instance, NULL);
505 if (mutex_result != EOK)
507 errno = mutex_result;
511 m_mutex_allocated =
true;
519 void dxMutexMutex::DoFinalizeObject()
521 if (m_mutex_allocated)
523 int mutex_result = pthread_mutex_destroy(&m_mutex_instance);
524 dICHECK(mutex_result == EOK || ((errno = mutex_result),
false));
526 m_mutex_allocated =
false;
531 void dxMutexMutex::LockMutex()
533 int lock_result = pthread_mutex_lock(&m_mutex_instance);
534 dICHECK(lock_result == EOK || ((errno = lock_result),
false));
537 bool dxMutexMutex::TryLockMutex()
539 int trylock_result = pthread_mutex_trylock(&m_mutex_instance);
540 dICHECK(trylock_result == EOK || trylock_result == EBUSY || ((errno = trylock_result),
false));
542 return trylock_result == EOK;
545 void dxMutexMutex::UnlockMutex()
547 int unlock_result = pthread_mutex_unlock(&m_mutex_instance);
548 dICHECK(unlock_result == EOK || ((errno = unlock_result),
false));
552 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
564 #if dBUILTIN_THREADING_IMPL_ENABLED
571 typedef dxtemplateJobListThreadedHandler<dxCondvarWakeup, dxMultiThreadedJobListContainer> dxMultiThreadedJobListHandler;
575 #endif // #if dBUILTIN_THREADING_IMPL_ENABLED
578 #endif // #if !defined(_WIN32)
581 #endif // #ifndef _ODE_THREADING_IMPL_POSIX_H_
Definition: threading_impl_templates.h:209
Definition: threading_impl_templates.h:444
Definition: threading_impl_templates.h:366
Definition: threading.h:154