blob: 7dec907df1076284cde4f0f00e32e1826bb42085 [file] [log] [blame]
bungeman@google.com55487522012-05-14 14:09:24 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkTypes.h"
9
10#include "SkThreadUtils.h"
11#include "SkThreadUtils_pthread.h"
12
13#include <pthread.h>
14#include <signal.h>
15
bungeman@google.com59bc8d42012-05-14 15:40:05 +000016PThreadEvent::PThreadEvent() : fConditionFlag(false) {
17 pthread_cond_init(&fCondition, NULL);
18 pthread_mutex_init(&fConditionMutex, NULL);
19}
20PThreadEvent::~PThreadEvent() {
21 pthread_mutex_destroy(&fConditionMutex);
22 pthread_cond_destroy(&fCondition);
23}
24void PThreadEvent::trigger() {
25 pthread_mutex_lock(&fConditionMutex);
26 fConditionFlag = true;
27 pthread_cond_signal(&fCondition);
28 pthread_mutex_unlock(&fConditionMutex);
29}
30void PThreadEvent::wait() {
31 pthread_mutex_lock(&fConditionMutex);
32 while (!fConditionFlag) {
33 pthread_cond_wait(&fCondition, &fConditionMutex);
34 }
35 pthread_mutex_unlock(&fConditionMutex);
36}
37bool PThreadEvent::isTriggered() {
38 bool currentFlag;
39 pthread_mutex_lock(&fConditionMutex);
40 currentFlag = fConditionFlag;
41 pthread_mutex_unlock(&fConditionMutex);
42 return currentFlag;
43}
44
bungeman@google.com55487522012-05-14 14:09:24 +000045SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
46 : fPThread()
47 , fValidPThread(false)
48 , fParam(data)
49 , fEntryPoint(entryPoint)
bungeman@google.com55487522012-05-14 14:09:24 +000050{
bungeman@google.com55487522012-05-14 14:09:24 +000051 pthread_attr_init(&fAttr);
52 pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
53}
bungeman@google.com59bc8d42012-05-14 15:40:05 +000054
bungeman@google.com55487522012-05-14 14:09:24 +000055SkThread_PThreadData::~SkThread_PThreadData() {
56 pthread_attr_destroy(&fAttr);
bungeman@google.com55487522012-05-14 14:09:24 +000057}
58
59static void* thread_start(void* arg) {
60 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
bungeman@google.com59bc8d42012-05-14 15:40:05 +000061 // Wait for start signal
62 pthreadData->fStarted.wait();
63
64 // Call entry point only if thread was not canceled before starting.
65 if (!pthreadData->fCanceled.isTriggered()) {
66 pthreadData->fEntryPoint(pthreadData->fParam);
bungeman@google.com55487522012-05-14 14:09:24 +000067 }
bungeman@google.com55487522012-05-14 14:09:24 +000068 return NULL;
69}
70
71SkThread::SkThread(entryPointProc entryPoint, void* data) {
72 SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
73 fData = pthreadData;
74
75 int ret = pthread_create(&(pthreadData->fPThread),
76 &(pthreadData->fAttr),
77 thread_start,
78 pthreadData);
79
80 pthreadData->fValidPThread = (0 == ret);
81}
82
83SkThread::~SkThread() {
84 if (fData != NULL) {
85 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
86 // If created thread but start was never called, kill the thread.
bungeman@google.com59bc8d42012-05-14 15:40:05 +000087 if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) {
88 pthreadData->fCanceled.trigger();
89 if (this->start()) {
90 this->join();
bungeman@google.com55487522012-05-14 14:09:24 +000091 }
92 }
93 delete pthreadData;
94 }
95}
96
97bool SkThread::start() {
98 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
99 if (!pthreadData->fValidPThread) {
100 return false;
101 }
102
bungeman@google.com59bc8d42012-05-14 15:40:05 +0000103 if (pthreadData->fStarted.isTriggered()) {
bungeman@google.com55487522012-05-14 14:09:24 +0000104 return false;
105 }
bungeman@google.com59bc8d42012-05-14 15:40:05 +0000106 pthreadData->fStarted.trigger();
bungeman@google.com55487522012-05-14 14:09:24 +0000107 return true;
108}
109
110void SkThread::join() {
111 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
bungeman@google.com59bc8d42012-05-14 15:40:05 +0000112 if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) {
bungeman@google.com55487522012-05-14 14:09:24 +0000113 return;
114 }
115
116 pthread_join(pthreadData->fPThread, NULL);
117}