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