I'm trying to run a thread with a function from a class member and use conditional variable to wait until the main thread signals and add the times the thread got signaled. Here is the code:
// Example program
#include <iostream>
#include <string>
#include <atomic>
#include <thread>
#include <unistd.h>
#include <mutex>
#include <condition_variable>
std::mutex m_mutex;
std::condition_variable m_condVar;
char stop =0;
class dummclass
{
std::thread dummclass_thread;
int alarms;
public:
dummclass() :
alarms(0),
dummclass_thread(std::thread(&dummclass::dummclassThreadProc, this))
{
}
~dummclass()
{
std::cout<<"Alarms: "<<alarms<<"\n";
//signal thread before joining
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
stop=1;
}
m_condVar.notify_one();
dummclass_thread.join();
}
private:
void dummclassThreadProc()
{
{
std::unique_lock<std::mutex> mlock(m_mutex);
std::cout<<"thread waiting\n";
m_condVar.wait(mlock);
std::cout<<"thread done waiting\n";
}
sleep(1);
std::unique_lock<std::mutex> mlock(m_mutex);
while (!stop)//!stop_dummclass.load())
{
std::cout<<"got mutex\n";
m_condVar.wait(mlock);
std::cout<<"wait done\n";
{
std::cout<<"got one\n";
alarms++;
}
}
std::cout<<"end loop\n";
}
};
int main()
{
dummclass *x = new dummclass;
sleep(3);
{
std::lock_guard<std::mutex> lock_guard(m_mutex);
}
m_condVar.notify_one();
std::cout<<"done waiting\n";
sleep(3);
for(int i=0;i<13;i++)
{
{
std::cout<<"signal "<<i<<"\n";
std::lock_guard<std::mutex> lock_guard(m_mutex);
}
m_condVar.notify_one();
}
delete x;
}
The weird part is that the initial waiting and signaling that are outside of the loops actually work ok. I don't understand what mistake I do so that the while loop inside the class thread doesn't catch any signal from the main thread but it catches a signal from the destructor of the dummyclass when I delete it. This is the output:
thread waiting
done waiting
thread done waiting
got mutex
signal 0 signal 1 signal 2 signal 3 signal 4 signal 5 signal 6 signal 7 signal 8 signal 9 signal 10 signal 11 signal 12
Alarms: 0
wait done
got one end loop
EDIT: It seems that adding a 1 second sleep in the main() for loop solves the problem. Is it possible that the for loop gets the mutex before wait() manages to wake and lock the mutex ?
for(int i=0;i<13;i++)
{
{std::cout<<"signal "<<i<<"\n";
std::lock_guard<std::mutex> lock_guard(m_mutex);}
m_condVar.notify_one();
sleep(1);
}
Can someone please show me what is wrong ?
Thanks.