blob: 17a2075ab048bb644172bfe87e27d8e269f2692d [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
16SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
17 : fPThread()
18 , fValidPThread(false)
19 , fParam(data)
20 , fEntryPoint(entryPoint)
21 , fStarted(false)
22{
23 pthread_mutex_init(&fStartMutex, NULL);
24
25 pthread_cond_init(&fStartCondition, NULL);
26
27 pthread_attr_init(&fAttr);
28 pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
29}
30SkThread_PThreadData::~SkThread_PThreadData() {
31 pthread_attr_destroy(&fAttr);
32 pthread_cond_destroy(&fStartCondition);
33 pthread_mutex_destroy(&fStartMutex);
34}
35
36static void* thread_start(void* arg) {
37 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
38 //Wait for start signal
39 pthread_mutex_lock(&(pthreadData->fStartMutex));
40 while (!pthreadData->fStarted) {
41 pthread_cond_wait(&(pthreadData->fStartCondition), &(pthreadData->fStartMutex));
42 }
43 pthread_mutex_unlock(&(pthreadData->fStartMutex));
44
45 //See if this thread was canceled before starting.
46 pthread_testcancel();
47
48 pthreadData->fEntryPoint(pthreadData->fParam);
49 return NULL;
50}
51
52SkThread::SkThread(entryPointProc entryPoint, void* data) {
53 SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
54 fData = pthreadData;
55
56 int ret = pthread_create(&(pthreadData->fPThread),
57 &(pthreadData->fAttr),
58 thread_start,
59 pthreadData);
60
61 pthreadData->fValidPThread = (0 == ret);
62}
63
64SkThread::~SkThread() {
65 if (fData != NULL) {
66 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
67 // If created thread but start was never called, kill the thread.
68 if (pthreadData->fValidPThread && !pthreadData->fStarted) {
69 if (pthread_cancel(pthreadData->fPThread) == 0) {
70 if (this->start()) {
71 this->join();
72 }
73 } else {
74 //kill with prejudice
75 pthread_kill(pthreadData->fPThread, SIGKILL);
76 }
77 }
78 delete pthreadData;
79 }
80}
81
82bool SkThread::start() {
83 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
84 if (!pthreadData->fValidPThread) {
85 return false;
86 }
87
88 if (pthreadData->fStarted) {
89 return false;
90 }
91 pthreadData->fStarted = true;
92 pthread_mutex_lock(&(pthreadData->fStartMutex));
93 pthread_cond_signal(&(pthreadData->fStartCondition));
94 pthread_mutex_unlock(&(pthreadData->fStartMutex));
95 return true;
96}
97
98void SkThread::join() {
99 SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
100 if (!pthreadData->fValidPThread || !pthreadData->fStarted) {
101 return;
102 }
103
104 pthread_join(pthreadData->fPThread, NULL);
105}