X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fplatform%2Fthreads.cpp;h=d168e906a671ddc8e0caab582c9ae30a58bd2853;hb=2ffc8cddcb866da58a4a45923823ad9fb1c296eb;hp=7c5b6ce4ed716de8cda00689de685482fca57eda;hpb=3424a2f327e569e92c7282c6e643536984a65c64;p=deb_libcec.git diff --git a/src/lib/platform/threads.cpp b/src/lib/platform/threads.cpp index 7c5b6ce..d168e90 100644 --- a/src/lib/platform/threads.cpp +++ b/src/lib/platform/threads.cpp @@ -35,9 +35,9 @@ using namespace CEC; -CMutex::CMutex(void) +CMutex::CMutex(bool bRecursive /* = true */) { - pthread_mutex_init(&m_mutex, NULL); + pthread_mutex_init(&m_mutex, bRecursive ? GetMutexAttribute() : NULL); } CMutex::~CMutex(void) @@ -60,10 +60,24 @@ void CMutex::Unlock(void) pthread_mutex_unlock(&m_mutex); } -CLockObject::CLockObject(CMutex *mutex) : +static pthread_mutexattr_t g_mutexAttr; +pthread_mutexattr_t *CMutex::GetMutexAttribute() +{ + static bool bAttributeInitialised = false; + if (!bAttributeInitialised) + { + pthread_mutexattr_init(&g_mutexAttr); + pthread_mutexattr_settype(&g_mutexAttr, PTHREAD_MUTEX_RECURSIVE); + bAttributeInitialised = true; + } + return &g_mutexAttr; +} + +CLockObject::CLockObject(CMutex *mutex, bool bTryLock /* = false */) : m_mutex(mutex) { - m_mutex->Lock(); + if (m_mutex) + m_bLocked = bTryLock ? m_mutex->TryLock() : m_mutex->Lock(); } CLockObject::~CLockObject(void) @@ -74,12 +88,17 @@ CLockObject::~CLockObject(void) void CLockObject::Leave(void) { - m_mutex->Unlock(); + if (m_mutex && m_bLocked) + { + m_bLocked = false; + m_mutex->Unlock(); + } } void CLockObject::Lock(void) { - m_mutex->Lock(); + if (m_mutex) + m_bLocked = m_mutex->Lock(); } CCondition::CCondition(void) @@ -93,56 +112,70 @@ CCondition::~CCondition(void) pthread_cond_destroy(&m_cond); } -void CCondition::Signal(void) +void CCondition::Broadcast(void) { pthread_cond_broadcast(&m_cond); } -bool CCondition::Wait(CMutex *mutex, int64_t iTimeout) +void CCondition::Signal(void) +{ + pthread_cond_signal(&m_cond); +} + +bool CCondition::Wait(CMutex *mutex, uint32_t iTimeout /* = 0 */) { bool bReturn(false); - struct timespec abstime; - struct timeval now; - if (gettimeofday(&now, NULL) == 0) + sched_yield(); + if (mutex) { - iTimeout += now.tv_usec / 1000; - abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000); - abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000); - bReturn = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0); + if (iTimeout > 0) + { + struct timespec abstime; + struct timeval now; + gettimeofday(&now, NULL); + iTimeout += now.tv_usec / 1000; + abstime.tv_sec = now.tv_sec + (time_t)(iTimeout / 1000); + abstime.tv_nsec = (int32_t)((iTimeout % (uint32_t)1000) * (uint32_t)1000000); + bReturn = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0); + } + else + { + bReturn = (pthread_cond_wait(&m_cond, &mutex->m_mutex) == 0); + } } return bReturn; } -void CCondition::Sleep(int iTimeout) +void CCondition::Sleep(uint32_t iTimeout) { - sched_yield(); CCondition w; CMutex m; CLockObject lock(&m); - w.Wait(&m, int64_t(iTimeout)); + w.Wait(&m, iTimeout); } CThread::CThread(void) : - m_bRunning(false), - m_bStop(false) + m_bStop(false), + m_bRunning(false) { } CThread::~CThread(void) { - m_bStop = true; - pthread_join(m_thread, NULL); + StopThread(); } -bool CThread::CreateThread(void) +bool CThread::CreateThread(bool bWait /* = true */) { bool bReturn(false); + CLockObject lock(&m_threadMutex); + m_bStop = false; if (!m_bRunning && pthread_create(&m_thread, NULL, (void *(*) (void *))&CThread::ThreadHandler, (void *)this) == 0) { - m_bRunning = true; - pthread_detach(m_thread); + if (bWait) + m_threadCondition.Wait(&m_threadMutex); bReturn = true; } @@ -151,14 +184,42 @@ bool CThread::CreateThread(void) void *CThread::ThreadHandler(CThread *thread) { + void *retVal = NULL; + if (thread) - return thread->Process(); - return NULL; + { + CLockObject lock(&thread->m_threadMutex); + thread->m_bRunning = true; + lock.Leave(); + thread->m_threadCondition.Broadcast(); + + retVal = thread->Process(); + + lock.Lock(); + thread->m_bRunning = false; + lock.Leave(); + thread->m_threadCondition.Broadcast(); + } + + return retVal; } -void CThread::StopThread(bool bWaitForExit /* = true */) +bool CThread::StopThread(bool bWaitForExit /* = true */) { + bool bReturn(true); m_bStop = true; - if (bWaitForExit) - pthread_join(m_thread, NULL); + + m_threadCondition.Broadcast(); + + void *retVal; + if (bWaitForExit && m_bRunning) + bReturn = (pthread_join(m_thread, &retVal) == 0); + + return bReturn; +} + +bool CThread::Sleep(uint32_t iTimeout) +{ + CLockObject lock(&m_threadMutex); + return m_bStop ? false : m_threadCondition.Wait(&m_threadMutex, iTimeout); }