Reputation: 63
I want the main
function to stop function_
when an event occurs (after 1ms in this example). The problem I have is that function_
immediately relock the mutex without letting the main
function to get it.
#include <thread>
#include <mutex>
#include <iostream>
#include <chrono>
using namespace std;
void function_(volatile bool *ptrStop, mutex *ptrMtx) {
for (int i = 0; i < 10; i++) {
ptrMtx->lock();
if (*ptrStop) {
ptrMtx->unlock();
return;
}
//doSomething();
this_thread::sleep_for(chrono::milliseconds(1));
cout << "Iteration " << i << endl;
ptrMtx->unlock();
//this_thread::sleep_for(chrono::milliseconds(1));
}
return;
}
int main() {
volatile bool stop = 0;
mutex mtx;
thread functionThread(function_, &stop, &mtx);
this_thread::sleep_for(chrono::milliseconds(1));
mtx.lock();
stop = 1;
mtx.unlock();
cout << "Changed boolean variable value" << endl;
functionThread.join();
system("pause");
return 0;
}
I got the following output :
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
Iteration 6
Iteration 7
Iteration 8
Iteration 9
Changed boolean variable value
What I want is to only do 1 or 2 iterations of function_
only (therefor let the main
take the mutex). How can I do that ? I heard about the std::condition_variable
but I couldn't figure a way to make what I want.
Moreover, if doSomething()
is uncommented and takes a long time to return, is there an easy way to kill the thread or force it to join without modifying what is in doSomething
function ?
Upvotes: 2
Views: 2185
Reputation: 17056
You don't need all that mechanism. An atomic<bool>
and join
will suffice.
Don't use lock
and unlock
. Use either unique_lock
or lock_guard
as appropriate.
Don't use volatile
unless you are dealing with memory-mapped hardware or unix signal-handlers.
SPOILER ----
#include <thread>
#include <mutex>
#include <iostream>
#include <chrono>
#include <atomic>
using namespace std; // Kids, don't try this at home.
using stopper = atomic<bool>;
void function_( stopper *ptrStop) {
for (int i = 0; i < 10; i++) {
if (*ptrStop) {
break;
}
//doSomething();
this_thread::sleep_for(chrono::milliseconds(10));
cout << "Iteration " << i << endl;
//this_thread::sleep_for(chrono::milliseconds(1));
}
*ptrStop = false;
return;
}
int main() {
stopper stop{ false };
thread functionThread(function_, &stop);
this_thread::sleep_for(chrono::milliseconds(100));
stop = true;
// // The following is optional
///while (stop == true) {
// this_thread::yield();
//}
cout << "Changed boolean variable value" << endl;
functionThread.join();
return 0;
}
Upvotes: 2
Reputation: 6993
I'm just going to answer this question:
Moreover, if doSomething() is uncommented and takes a long time to return, is there an easy way to kill the thread or force it to join without modifying what is in doSomething function?
The answer is no. If you try and kill the thread in any way, you can not be sure that it's been killed at a time when it was harmless to other threads to do so. For example; your c++ library could implement new with a mutex; if you're in the middle of creating a new object when your thread is killed; the mutex will remain locked for ever; leaving all other threads unable to call new. This will result in your program deadlocking in a way that you'll never be able to debug.
The only way you can do this reliably is do a little work in doSomething()
; and then check to see if you can go back and do more.
Upvotes: 1