180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThreadUtils.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThreadUtils_pthread.h" 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <pthread.h> 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <signal.h> 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruPThreadEvent::PThreadEvent() : fConditionFlag(false) { 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_cond_init(&fCondition, NULL); 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_init(&fConditionMutex, NULL); 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruPThreadEvent::~PThreadEvent() { 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_destroy(&fConditionMutex); 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_cond_destroy(&fCondition); 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid PThreadEvent::trigger() { 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_lock(&fConditionMutex); 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fConditionFlag = true; 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_cond_signal(&fCondition); 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_unlock(&fConditionMutex); 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid PThreadEvent::wait() { 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_lock(&fConditionMutex); 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (!fConditionFlag) { 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_cond_wait(&fCondition, &fConditionMutex); 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_unlock(&fConditionMutex); 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool PThreadEvent::isTriggered() { 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool currentFlag; 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_lock(&fConditionMutex); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru currentFlag = fConditionFlag; 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutex_unlock(&fConditionMutex); 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return currentFlag; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data) 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru : fPThread() 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fValidPThread(false) 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fParam(data) 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru , fEntryPoint(entryPoint) 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_attr_init(&fAttr); 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE); 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread_PThreadData::~SkThread_PThreadData() { 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_attr_destroy(&fAttr); 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void* thread_start(void* arg) { 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg); 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Wait for start signal 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData->fStarted.wait(); 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Call entry point only if thread was not canceled before starting. 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!pthreadData->fCanceled.isTriggered()) { 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData->fEntryPoint(pthreadData->fParam); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread::SkThread(entryPointProc entryPoint, void* data) { 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data); 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru fData = pthreadData; 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int ret = pthread_create(&(pthreadData->fPThread), 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru &(pthreadData->fAttr), 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru thread_start, 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData); 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData->fValidPThread = (0 == ret); 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkThread::~SkThread() { 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fData != NULL) { 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // If created thread but start was never called, kill the thread. 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) { 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData->fCanceled.trigger(); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->start()) { 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->join(); 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru delete pthreadData; 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkThread::start() { 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!pthreadData->fValidPThread) { 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (pthreadData->fStarted.isTriggered()) { 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return false; 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthreadData->fStarted.trigger(); 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return true; 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkThread::join() { 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData); 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) { 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_join(pthreadData->fPThread, NULL); 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 118