I've a problem with some code with the same logic of the following one:
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
int main() {
std::condition_variable myCV;
std::mutex myMutex;
std::unique_lock myLock(myMutex);
bool isRunning{ true };
std::jthread myThread([&isRunning, &myCV, &myLock]() {
while (isRunning) {
myCV.wait(myLock);
// do some work here
}
std::cout << "Exited from myThread while loop." << std::endl;
});
for (int i = 0; i < 100; i++) {
myCV.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
std::cout << "Test loop " << i << std::endl;
}
isRunning = false;
myCV.notify_one();
return 0;
}
Basically, I've a loop where i do some work, and when my work is done at every iteration I call a method in another thread for handling the data without blocking the main thread; in order to avoid to create and destruct the thread every time, I'm using a loop inside that thread with a std::condition_variable
for starting to manage the data when they are ready.
The logic works well but I've a problem when exiting the program; if I run the code I've an error when the program ends, because the mutex destructor calls abort()
:
...\stl\src\mutex.cpp(164): unlock of unowned mutex
If I comment the following row myCV.notify_one();
the program continues to run without stopping.
How can I exit the program gracefully without any error? What I'm doing wrong?
Thanks for your comments. The problem was in fact the mutex that was unlocked in a thread different from the one that acquired it. Moving the lock definition inside the thread code solved the problem:
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
int main() {
std::condition_variable myCV;
std::mutex myMutex;
bool isRunning{ true };
std::jthread myThread([&isRunning, &myCV, &myMutex]() {
std::unique_lock myLock(myMutex);
while (isRunning) {
myCV.wait(myLock);
// do some work here
}
std::cout << "Exited from myThread while loop." << std::endl;
});
for (int i = 0; i < 100; i++) {
myCV.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
std::cout << "Test loop " << i << std::endl;
}
isRunning = false;
myCV.notify_one();
return 0;
}