From 59bc8d4fa725da2a6cec3526859c488b577d5cce Mon Sep 17 00:00:00 2001 From: "bungeman@google.com" Date: Mon, 14 May 2012 15:40:05 +0000 Subject: [PATCH] Android does not support pthread_cancel / pthread_testcancel. git-svn-id: http://skia.googlecode.com/svn/trunk@3923 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/utils/SkThreadUtils_pthread.cpp | 74 +++++++++++++++++------------ src/utils/SkThreadUtils_pthread.h | 22 +++++++-- src/utils/SkThreadUtils_win.h | 2 +- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/utils/SkThreadUtils_pthread.cpp b/src/utils/SkThreadUtils_pthread.cpp index 17a2075ab0..7dec907df1 100644 --- a/src/utils/SkThreadUtils_pthread.cpp +++ b/src/utils/SkThreadUtils_pthread.cpp @@ -13,39 +13,58 @@ #include #include +PThreadEvent::PThreadEvent() : fConditionFlag(false) { + pthread_cond_init(&fCondition, NULL); + pthread_mutex_init(&fConditionMutex, NULL); +} +PThreadEvent::~PThreadEvent() { + pthread_mutex_destroy(&fConditionMutex); + pthread_cond_destroy(&fCondition); +} +void PThreadEvent::trigger() { + pthread_mutex_lock(&fConditionMutex); + fConditionFlag = true; + pthread_cond_signal(&fCondition); + pthread_mutex_unlock(&fConditionMutex); +} +void PThreadEvent::wait() { + pthread_mutex_lock(&fConditionMutex); + while (!fConditionFlag) { + pthread_cond_wait(&fCondition, &fConditionMutex); + } + pthread_mutex_unlock(&fConditionMutex); +} +bool PThreadEvent::isTriggered() { + bool currentFlag; + pthread_mutex_lock(&fConditionMutex); + currentFlag = fConditionFlag; + pthread_mutex_unlock(&fConditionMutex); + return currentFlag; +} + SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data) : fPThread() , fValidPThread(false) , fParam(data) , fEntryPoint(entryPoint) - , fStarted(false) { - pthread_mutex_init(&fStartMutex, NULL); - - pthread_cond_init(&fStartCondition, NULL); - pthread_attr_init(&fAttr); pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE); } + SkThread_PThreadData::~SkThread_PThreadData() { pthread_attr_destroy(&fAttr); - pthread_cond_destroy(&fStartCondition); - pthread_mutex_destroy(&fStartMutex); } static void* thread_start(void* arg) { SkThread_PThreadData* pthreadData = static_cast(arg); - //Wait for start signal - pthread_mutex_lock(&(pthreadData->fStartMutex)); - while (!pthreadData->fStarted) { - pthread_cond_wait(&(pthreadData->fStartCondition), &(pthreadData->fStartMutex)); + // Wait for start signal + pthreadData->fStarted.wait(); + + // Call entry point only if thread was not canceled before starting. + if (!pthreadData->fCanceled.isTriggered()) { + pthreadData->fEntryPoint(pthreadData->fParam); } - pthread_mutex_unlock(&(pthreadData->fStartMutex)); - - //See if this thread was canceled before starting. - pthread_testcancel(); - - pthreadData->fEntryPoint(pthreadData->fParam); return NULL; } @@ -65,14 +84,10 @@ SkThread::~SkThread() { if (fData != NULL) { SkThread_PThreadData* pthreadData = static_cast(fData); // If created thread but start was never called, kill the thread. - if (pthreadData->fValidPThread && !pthreadData->fStarted) { - if (pthread_cancel(pthreadData->fPThread) == 0) { - if (this->start()) { - this->join(); - } - } else { - //kill with prejudice - pthread_kill(pthreadData->fPThread, SIGKILL); + if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) { + pthreadData->fCanceled.trigger(); + if (this->start()) { + this->join(); } } delete pthreadData; @@ -85,19 +100,16 @@ bool SkThread::start() { return false; } - if (pthreadData->fStarted) { + if (pthreadData->fStarted.isTriggered()) { return false; } - pthreadData->fStarted = true; - pthread_mutex_lock(&(pthreadData->fStartMutex)); - pthread_cond_signal(&(pthreadData->fStartCondition)); - pthread_mutex_unlock(&(pthreadData->fStartMutex)); + pthreadData->fStarted.trigger(); return true; } void SkThread::join() { SkThread_PThreadData* pthreadData = static_cast(fData); - if (!pthreadData->fValidPThread || !pthreadData->fStarted) { + if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) { return; } diff --git a/src/utils/SkThreadUtils_pthread.h b/src/utils/SkThreadUtils_pthread.h index 52b398c2e2..3e1020275c 100644 --- a/src/utils/SkThreadUtils_pthread.h +++ b/src/utils/SkThreadUtils_pthread.h @@ -11,19 +11,33 @@ #include "SkThreadUtils.h" #include -class SkThread_PThreadData { +class PThreadEvent : SkNoncopyable { +public: + PThreadEvent(); + ~PThreadEvent(); + void trigger(); + void wait(); + bool isTriggered(); + +private: + pthread_cond_t fCondition; + pthread_mutex_t fConditionMutex; + bool fConditionFlag; +}; + +class SkThread_PThreadData : SkNoncopyable { public: SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data); ~SkThread_PThreadData(); pthread_t fPThread; bool fValidPThread; - pthread_mutex_t fStartMutex; - pthread_cond_t fStartCondition; + PThreadEvent fStarted; + PThreadEvent fCanceled; + pthread_attr_t fAttr; void* fParam; SkThread::entryPointProc fEntryPoint; - bool fStarted; }; #endif diff --git a/src/utils/SkThreadUtils_win.h b/src/utils/SkThreadUtils_win.h index 5861e5d0db..51b32fad6f 100644 --- a/src/utils/SkThreadUtils_win.h +++ b/src/utils/SkThreadUtils_win.h @@ -12,7 +12,7 @@ #include "SkThreadUtils.h" -class SkThread_WinData { +class SkThread_WinData : SkNoncopyable { public: SkThread_WinData(SkThread::entryPointProc entryPoint, void* data); ~SkThread_WinData();