framework2
182 строки · 4.6 Кб
1#include "ofThread.h"
2#include "ofLog.h"
3
4#ifdef TARGET_ANDROID
5#include <jni.h>
6#include "ofxAndroidUtils.h"
7#endif
8
9//-------------------------------------------------
10ofThread::ofThread()
11:threadRunning(false)
12,threadDone(true)
13,mutexBlocks(true)
14,name(""){
15}
16
17//-------------------------------------------------
18bool ofThread::isThreadRunning() const{
19return threadRunning;
20}
21
22//-------------------------------------------------
23std::thread::id ofThread::getThreadId() const{
24return thread.get_id();
25}
26
27//-------------------------------------------------
28std::string ofThread::getThreadName() const{
29return name;
30}
31
32//-------------------------------------------------
33void ofThread::setThreadName(const std::string & name){
34this->name = name;
35}
36
37//-------------------------------------------------
38void ofThread::startThread(){
39std::unique_lock<std::mutex> lck(mutex);
40if(threadRunning || !threadDone){
41ofLogWarning("ofThread") << "- name: " << getThreadName() << " - Cannot start, thread already running.";
42return;
43}
44
45threadDone = false;
46threadRunning = true;
47this->mutexBlocks = true;
48
49thread = std::thread(std::bind(&ofThread::run,this));
50}
51
52//-------------------------------------------------
53void ofThread::startThread(bool mutexBlocks){
54std::unique_lock<std::mutex> lck(mutex);
55if(threadRunning || !threadDone){
56ofLogWarning("ofThread") << "- name: " << getThreadName() << " - Cannot start, thread already running.";
57return;
58}
59
60threadDone = false;
61threadRunning = true;
62this->mutexBlocks = mutexBlocks;
63
64thread = std::thread(std::bind(&ofThread::run,this));
65}
66
67//-------------------------------------------------
68bool ofThread::lock(){
69if(mutexBlocks){
70mutex.lock();
71}else{
72if(!mutex.try_lock()){
73return false; // mutex is locked, tryLock failed
74}
75}
76return true;
77}
78
79//-------------------------------------------------
80bool ofThread::tryLock(){
81return mutex.try_lock();
82}
83
84//-------------------------------------------------
85void ofThread::unlock(){
86mutex.unlock();
87}
88
89//-------------------------------------------------
90void ofThread::stopThread(){
91threadRunning = false;
92}
93
94//-------------------------------------------------
95void ofThread::waitForThread(bool callStopThread, long milliseconds){
96if(!threadDone){
97// tell thread to stop
98if(callStopThread){
99stopThread();
100}
101
102// wait for the thread to finish
103if(isCurrentThread()){
104return; // waitForThread should only be called outside thread
105}
106
107if (INFINITE_JOIN_TIMEOUT == milliseconds){
108std::unique_lock<std::mutex> lck(mutex);
109if(!threadDone){
110condition.wait(lck);
111}
112}else{
113// Wait for "joinWaitMillis" milliseconds for thread to finish
114std::unique_lock<std::mutex> lck(mutex);
115if(!threadDone && condition.wait_for(lck,std::chrono::milliseconds(milliseconds))==std::cv_status::timeout){
116// unable to completely wait for thread
117}
118}
119}
120}
121
122//-------------------------------------------------
123void ofThread::sleep(long milliseconds){
124std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
125}
126
127//-------------------------------------------------
128void ofThread::yield(){
129std::this_thread::yield();
130}
131
132//-------------------------------------------------
133bool ofThread::isCurrentThread() const{
134return std::this_thread::get_id() == thread.get_id();
135}
136
137//-------------------------------------------------
138std::thread & ofThread::getNativeThread(){
139return thread;
140}
141
142//-------------------------------------------------
143const std::thread & ofThread::getNativeThread() const{
144return thread;
145}
146
147//-------------------------------------------------
148void ofThread::threadedFunction(){
149ofLogWarning("ofThread") << "- name: " << getThreadName() << " - Override ofThread::threadedFunction() in your ofThread subclass.";
150}
151
152//-------------------------------------------------
153void ofThread::run(){
154#ifdef TARGET_ANDROID
155JNIEnv * env;
156jint attachResult = ofGetJavaVMPtr()->AttachCurrentThread(&env,nullptr);
157if(attachResult!=0){
158ofLogWarning() << "couldn't attach new thread to java vm";
159}
160#endif
161
162// user function
163// should loop endlessly.
164try{
165threadedFunction();
166}catch(const std::exception& exc){
167ofLogFatalError("ofThreadErrorLogger::exception") << exc.what();
168}catch(...){
169ofLogFatalError("ofThreadErrorLogger::exception") << "Unknown exception.";
170}
171try{
172thread.detach();
173}catch(...){}
174#ifdef TARGET_ANDROID
175attachResult = ofGetJavaVMPtr()->DetachCurrentThread();
176#endif
177
178std::unique_lock<std::mutex> lck(mutex);
179threadRunning = false;
180threadDone = true;
181condition.notify_all();
182}
183