1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkThreadUtils_pthread.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,117 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkTypes.h" 1.12 + 1.13 +#include "SkThreadUtils.h" 1.14 +#include "SkThreadUtils_pthread.h" 1.15 + 1.16 +#include <pthread.h> 1.17 +#include <signal.h> 1.18 + 1.19 +PThreadEvent::PThreadEvent() : fConditionFlag(false) { 1.20 + pthread_cond_init(&fCondition, NULL); 1.21 + pthread_mutex_init(&fConditionMutex, NULL); 1.22 +} 1.23 +PThreadEvent::~PThreadEvent() { 1.24 + pthread_mutex_destroy(&fConditionMutex); 1.25 + pthread_cond_destroy(&fCondition); 1.26 +} 1.27 +void PThreadEvent::trigger() { 1.28 + pthread_mutex_lock(&fConditionMutex); 1.29 + fConditionFlag = true; 1.30 + pthread_cond_signal(&fCondition); 1.31 + pthread_mutex_unlock(&fConditionMutex); 1.32 +} 1.33 +void PThreadEvent::wait() { 1.34 + pthread_mutex_lock(&fConditionMutex); 1.35 + while (!fConditionFlag) { 1.36 + pthread_cond_wait(&fCondition, &fConditionMutex); 1.37 + } 1.38 + pthread_mutex_unlock(&fConditionMutex); 1.39 +} 1.40 +bool PThreadEvent::isTriggered() { 1.41 + bool currentFlag; 1.42 + pthread_mutex_lock(&fConditionMutex); 1.43 + currentFlag = fConditionFlag; 1.44 + pthread_mutex_unlock(&fConditionMutex); 1.45 + return currentFlag; 1.46 +} 1.47 + 1.48 +SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data) 1.49 + : fPThread() 1.50 + , fValidPThread(false) 1.51 + , fParam(data) 1.52 + , fEntryPoint(entryPoint) 1.53 +{ 1.54 + pthread_attr_init(&fAttr); 1.55 + pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE); 1.56 +} 1.57 + 1.58 +SkThread_PThreadData::~SkThread_PThreadData() { 1.59 + pthread_attr_destroy(&fAttr); 1.60 +} 1.61 + 1.62 +static void* thread_start(void* arg) { 1.63 + SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg); 1.64 + // Wait for start signal 1.65 + pthreadData->fStarted.wait(); 1.66 + 1.67 + // Call entry point only if thread was not canceled before starting. 1.68 + if (!pthreadData->fCanceled.isTriggered()) { 1.69 + pthreadData->fEntryPoint(pthreadData->fParam); 1.70 + } 1.71 + return NULL; 1.72 +} 1.73 + 1.74 +SkThread::SkThread(entryPointProc entryPoint, void* data) { 1.75 + SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data); 1.76 + fData = pthreadData; 1.77 + 1.78 + int ret = pthread_create(&(pthreadData->fPThread), 1.79 + &(pthreadData->fAttr), 1.80 + thread_start, 1.81 + pthreadData); 1.82 + 1.83 + pthreadData->fValidPThread = (0 == ret); 1.84 +} 1.85 + 1.86 +SkThread::~SkThread() { 1.87 + if (fData != NULL) { 1.88 + SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 1.89 + // If created thread but start was never called, kill the thread. 1.90 + if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) { 1.91 + pthreadData->fCanceled.trigger(); 1.92 + if (this->start()) { 1.93 + this->join(); 1.94 + } 1.95 + } 1.96 + delete pthreadData; 1.97 + } 1.98 +} 1.99 + 1.100 +bool SkThread::start() { 1.101 + SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 1.102 + if (!pthreadData->fValidPThread) { 1.103 + return false; 1.104 + } 1.105 + 1.106 + if (pthreadData->fStarted.isTriggered()) { 1.107 + return false; 1.108 + } 1.109 + pthreadData->fStarted.trigger(); 1.110 + return true; 1.111 +} 1.112 + 1.113 +void SkThread::join() { 1.114 + SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 1.115 + if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) { 1.116 + return; 1.117 + } 1.118 + 1.119 + pthread_join(pthreadData->fPThread, NULL); 1.120 +}