Line data Source code
1 : /*
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 :
16 0 : PThreadEvent::PThreadEvent() : fConditionFlag(false) {
17 0 : pthread_cond_init(&fCondition, nullptr);
18 0 : pthread_mutex_init(&fConditionMutex, nullptr);
19 0 : }
20 0 : PThreadEvent::~PThreadEvent() {
21 0 : pthread_mutex_destroy(&fConditionMutex);
22 0 : pthread_cond_destroy(&fCondition);
23 0 : }
24 0 : void PThreadEvent::trigger() {
25 0 : pthread_mutex_lock(&fConditionMutex);
26 0 : fConditionFlag = true;
27 0 : pthread_cond_signal(&fCondition);
28 0 : pthread_mutex_unlock(&fConditionMutex);
29 0 : }
30 0 : void PThreadEvent::wait() {
31 0 : pthread_mutex_lock(&fConditionMutex);
32 0 : while (!fConditionFlag) {
33 0 : pthread_cond_wait(&fCondition, &fConditionMutex);
34 : }
35 0 : pthread_mutex_unlock(&fConditionMutex);
36 0 : }
37 0 : bool PThreadEvent::isTriggered() {
38 : bool currentFlag;
39 0 : pthread_mutex_lock(&fConditionMutex);
40 0 : currentFlag = fConditionFlag;
41 0 : pthread_mutex_unlock(&fConditionMutex);
42 0 : return currentFlag;
43 : }
44 :
45 0 : SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
46 : : fPThread()
47 : , fValidPThread(false)
48 : , fParam(data)
49 0 : , fEntryPoint(entryPoint)
50 : {
51 0 : pthread_attr_init(&fAttr);
52 0 : pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
53 0 : }
54 :
55 0 : SkThread_PThreadData::~SkThread_PThreadData() {
56 0 : pthread_attr_destroy(&fAttr);
57 0 : }
58 :
59 0 : static void* thread_start(void* arg) {
60 0 : SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
61 : // Wait for start signal
62 0 : pthreadData->fStarted.wait();
63 :
64 : // Call entry point only if thread was not canceled before starting.
65 0 : if (!pthreadData->fCanceled.isTriggered()) {
66 0 : pthreadData->fEntryPoint(pthreadData->fParam);
67 : }
68 0 : return nullptr;
69 : }
70 :
71 0 : SkThread::SkThread(entryPointProc entryPoint, void* data) {
72 0 : SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
73 0 : fData = pthreadData;
74 :
75 0 : int ret = pthread_create(&(pthreadData->fPThread),
76 0 : &(pthreadData->fAttr),
77 : thread_start,
78 0 : pthreadData);
79 :
80 0 : pthreadData->fValidPThread = (0 == ret);
81 0 : }
82 :
83 0 : SkThread::~SkThread() {
84 0 : if (fData != nullptr) {
85 0 : SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
86 : // If created thread but start was never called, kill the thread.
87 0 : if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) {
88 0 : pthreadData->fCanceled.trigger();
89 0 : if (this->start()) {
90 0 : this->join();
91 : }
92 : }
93 0 : delete pthreadData;
94 : }
95 0 : }
96 :
97 0 : bool SkThread::start() {
98 0 : SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
99 0 : if (!pthreadData->fValidPThread) {
100 0 : return false;
101 : }
102 :
103 0 : if (pthreadData->fStarted.isTriggered()) {
104 0 : return false;
105 : }
106 0 : pthreadData->fStarted.trigger();
107 0 : return true;
108 : }
109 :
110 0 : void SkThread::join() {
111 0 : SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
112 0 : if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) {
113 0 : return;
114 : }
115 :
116 0 : pthread_join(pthreadData->fPThread, nullptr);
117 : }
|