Wake thread and exit from sleep - c++

I have a singleton class which looks something like:
//Test.h
class Test
{
private:
static std::mutex mtx;
static std::condition_variable cv;
static bool end;
static void DoSomethingThread();
static void SomeOtherFunction();
public:
static void Start();
}
//Test.cpp
std::mutex Test::mtx;
std::condition_variable Test::cv;
bool Test::end = false;
void Test::Start()
{
std::thread t_thread(Test::DoSomethingThread);
while(a) {
if (b) {
// End thread.
std::unique_lock<std::mutex> lock(mtx);
Test::end = true;
Test::cv.notify_one();
t_thread.join();
Test::SomeOtherFunction();
// Restart thread.
Test::end = false;
t_thread = std::thread(Test::DoSomethingThread);
}
...
}
}
void Test::DoSomethingThread()
{
std::unique_lock<std::mutex> lock(mtx);
while (1) {
//Do some work here.
Test::cv.wait_for(lock, std::chrono::seconds(1000), []() { return Test::end; });
if (Test::end) { break; }
}
}
I found this code on this page and to be honest dont really know how this works. But the guy had the same problem as me and I thought it would work for my case to, but it didnt.
So what I currently have is have a thread t_thread which runs forever, it does some work and then sleeps for 1000 seconds and all over again. What I need is some way to wake this thread up from sleep and exit it. So SomeOtherFunction() can do its work and then restart the thread.
Why doesnt this code works, and how can I make it work?

I went back to original post and did:
if (b) {
{
// End thread.
std::unique_lock<std::mutex> lock(mtx);
Test::end = true;
Test::cv.notify_one();
}
t_thread.join();
Test::SomeOtherFunction();
// Restart thread.
Test::end = false;
t_thread = std::thread(Test::DoSomethingThread);
}
And it works now. Thanks anyway.

Related

boost::threadpool::pool::wait() doesn't stop

I was trying to write some Task-Management class with C++ boost::threadpool, condition_variable and mutex. It seems the program will stop at boost::threadpool::pool::wait(), but I don't know why this happens.
#include <boost/threadpool.hpp>
#include <condition_variable>
#include <iostream>
#include <mutex>
using namespace std;
enum {
Running,
Stopped,
Exiting
};
class C {
private:
int m_iStatus;
mutex m_mtx;
condition_variable m_cond;
boost::threadpool::pool m_tp;
public:
C() : m_iStatus(Stopped), m_tp(8) {}
void Start();
void Exit();
private:
bool Check();
void Dispatcher();
};
bool C::Check()
{
unique_lock<mutex> lk(m_mtx);
if (m_iStatus == Stopped)
m_cond.wait(lk);
if (m_iStatus == Exiting)
return false;
else
return true;
}
void C::Dispatcher()
{
if (!Check())
return;
unique_lock<mutex> lk(m_mtx);
// do something...
cout << "." << endl;
m_tp.schedule(bind(&C::Dispatcher, this));
}
void C::Start()
{
unique_lock<mutex> lk(m_mtx);
m_iStatus = Running;
m_tp.schedule(bind(&C::Dispatcher, this));
}
void C::Exit()
{
unique_lock<mutex> lk(m_mtx);
m_iStatus = Exiting;
m_cond.notify_all(); /* notify those waiting on m_cond */
m_tp.wait(); /* went wrong here */
}
int main()
{
C c;
c.Start();
/* wait for a moment */
Sleep(1000);
/* then call Exit */
c.Exit();
return 0;
}
You enter the wait call while still holding the mutex. This will prevent other thread's from completing their work.
In your particular case, the m_cond condition variable is waiting on that same mutex, so the call to m_cond.wait(lk); will be unable to return as long as the mutex is still being held by the other thread.
One solution to this would be to relinquish the lock on the mutex between notifying the condition variable and waiting for the thread pool to complete:
{
unique_lock<mutex> lk(m_mtx);
m_iStatus = Exiting;
m_cond.notify_all(); /* notify those waiting on m_cond */
} // lock on m_mtx gets released here
m_tp.wait(); /* this should run fine now */

How to "stop" detached thread which is waiting on a condition variable?

I detach a thread from Class B:
t1 = std::thread(&Class::method, this);
t1.detach();
which as part of it's normal operation waits on a condition variable:
cv.wait(lock);
However, when I close my B application the detached thread remains. How do I stop/clean-up this thread when B::~B() is called?
Try this snippet: Set bool member variable discard_ to true to avoid execution of your scheduled process execution:
std::thread([&](){
std::lock_guard<std::mutex> lock(mutex_);
cv.wait(lock,[](){ return normal_predicate_here || discard_ ;});
if(discard_) return;
// execute scheduled process
}).detach();
Make the other thread cooperate for termination. Non-detached thread makes it easier to terminate cleanly, so that you do not destroy the state accessed by the other thread prematurely:
struct OtherThread {
std::mutex m_;
std::condition_variable c_;
bool stop_ = false;
std::thread t_;
void thread_function() {
for(;;) {
std::unique_lock<std::mutex> l(m_);
while(!stop_ /* || a-message-received */)
c_.wait(l);
if(stop_)
return;
// Process a message.
// ...
// Continue waiting for messages or stop.
}
}
~OtherThread() {
this->stop();
}
void stop() {
{
std::unique_lock<std::mutex> l(m_);
if(stop_)
return;
stop_ = true;
}
c_.notify_one();
t_.join(); // Wait till the thread exited, so that this object can be destroyed.
}
};

C++11 Watchdog class, test application doesn't want to exit

I am using an online C++11 compiler, link found here: cpp.sh (C++ Shell).
In my current project, I would like to have a watchdog class, to be able to check somehow the status of a thread or FSM (for example).
After some work (I'm not a C++11 guru), I finally got the code below, that compiles ok.
I also did some basic/trivial tests, but it seems the test program doesn't want to exit.
It says "Program running" and the only way to (force) exit is to hit the "Stop" button... :(
Well, my question : What am I doing wrong?
Any ideas, suggestions you can provide are highly appreciated.
Here is the full code, including my test app:
Watchdog (as MCVE):
#include <thread>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <iostream>
using namespace std::chrono;
class Watchdog
{
public:
Watchdog();
~Watchdog();
void Start(unsigned int milliseconds, std::function<void()> callback = 0);
void Stop();
void Pet();
private:
unsigned int m_interval;
std::atomic<bool> m_running;
std::thread m_thread;
std::function<void()> m_callback;
std::mutex m_mutex;
steady_clock::time_point m_lastPetTime;
std::condition_variable m_stopCondition;
void Loop();
};
Watchdog::Watchdog()
{
m_running = false;
}
Watchdog::~Watchdog()
{
Stop();
}
void Watchdog::Start(unsigned int milliseconds, std::function<void()> callback)
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == false)
{
m_lastPetTime = steady_clock::now();
m_interval = milliseconds;
m_callback = callback;
m_running = true;
m_thread = std::thread(&Watchdog::Loop, this);
}
}
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
}
}
void Watchdog::Pet()
{
std::unique_lock<std::mutex> locker(m_mutex);
m_lastPetTime = steady_clock::now();
m_stopCondition.notify_all();
}
void Watchdog::Loop()
{
std::unique_lock<std::mutex> locker(m_mutex);
while(m_running == true)
{
if(m_stopCondition.wait_for(locker, milliseconds(m_interval)) == std::cv_status::timeout)
{
if(m_callback != nullptr)
m_callback();
}
}
}
int main(int argc, char *argv[])
{
Watchdog wdog;
wdog.Start(3000, [] { std::cout << " WDOG TRIGGERED!!! "; });
for(auto i = 0; i < 10; i++)
{
std::cout << "[+]";
wdog.Pet();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
-
You're doing a deadlock here.
void Watchdog::Stop()
{
std::unique_lock<std::mutex> locker(m_mutex);
if(m_running == true)
{
m_running = false;
m_stopCondition.notify_all();
m_thread.join();
^ ~~~~~~~~~~~~~~
m_mutex is locked; m_thread cannot continue execution
}
}
Some additional suggestion: use simple if conditions, do not compare with true or false.

Threaded timer, interrupting a sleep (stopping it)

I'm wanting a reasonably reliable threaded timer, so I've written a timer object that fires a std::function on a thread. I would like to give this timer the ability to stop before it gets to the next tick; something you can't do with ::sleep (at least I don't think you can).
So what I've done is put a condition variable on a mutex. If the condition times out, I fire the event. If the condition is signalled the thread is exited. So the Stop method needs to be able to get the thread to stop and/or interrupt its wait, which I think is what it's doing right now.
There are problems with this however. Sometimes the thread isn't joinable() and sometimes the condition is signalled after its timeout but before it's put into its wait state.
How can I improve this and make it robust?
The following is a full repo. The wait is 10 seconds here but the program should terminate immediately as the Foo is created and then immediately destroyed. It does sometimes but mostly it does not.
#include <atomic>
#include <thread>
#include <future>
#include <sstream>
#include <chrono>
#include <iostream>
class Timer
{
public:
Timer() {}
~Timer()
{
Stop();
}
void Start(std::chrono::milliseconds const & interval, std::function<void(void)> const & callback)
{
Stop();
thread = std::thread([=]()
{
for(;;)
{
auto locked = std::unique_lock<std::mutex>(mutex);
auto result = terminate.wait_for(locked, interval);
if (result == std::cv_status::timeout)
{
callback();
}
else
{
return;
}
}
});
}
void Stop()
{
terminate.notify_one();
if(thread.joinable())
{
thread.join();
}
}
private:
std::thread thread;
std::mutex mutex;
std::condition_variable terminate;
};
class Foo
{
public:
Foo()
{
timer = std::make_unique<Timer>();
timer->Start(std::chrono::milliseconds(10000), std::bind(&Foo::Callback, this));
}
~Foo()
{
}
void Callback()
{
static int count = 0;
std::ostringstream o;
std::cout << count++ << std::endl;
}
std::unique_ptr<Timer> timer;
};
int main(void)
{
{
Foo foo;
}
return 0;
}
See my comment. You forgot to implement the state of the thing the thread is waiting for, leaving the mutex nothing to protect and the thread nothing to wait for. Condition variables are stateless -- your code must track the state of the thing whose change you're notifying the thread about.
Here's the code fixed. Notice that the mutex protects stop, and stop is the thing the thread is waiting for.
class Timer
{
public:
Timer() {}
~Timer()
{
Stop();
}
void Start(std::chrono::milliseconds const & interval,
std::function<void(void)> const & callback)
{
Stop();
{
auto locked = std::unique_lock<std::mutex>(mutex);
stop = false;
}
thread = std::thread([=]()
{
auto locked = std::unique_lock<std::mutex>(mutex);
while (! stop) // We hold the mutex that protects stop
{
auto result = terminate.wait_for(locked, interval);
if (result == std::cv_status::timeout)
{
callback();
}
}
});
}
void Stop()
{
{
// Set the predicate
auto locked = std::unique_lock<std::mutex>(mutex);
stop = true;
}
// Tell the thread the predicate has changed
terminate.notify_one();
if(thread.joinable())
{
thread.join();
}
}
private:
bool stop; // This is the thing the thread is waiting for
std::thread thread;
std::mutex mutex;
std::condition_variable terminate;
};

Reading a flag in a boost thread

I am kind of a newbie in Boost programming. What I want to do is create a thread from main() which will run continuously until the main() exits. Now, I am doing some operations on that thread and when it is done it will set a boolean flag. The main() will wait for this flag to be set, and when it is 'true' the main() will do its work, reset the flag, and wait for it to be set again. The other thread will run continuously.
Can anyone please provide a simple set of boost thread instructions to achieve this?
I am trying to do this in pseudocode
class Call {
public:
bool flag, do_it;
keyboard_callback() {
if('s' pressed) do_it = true;
}
f() { // some callback function
if(do_it == true) flag=true;
}
void func() {
...register callback f()
...register keyboard_callback()
...
while(some condition) { keep running , exit when 'q'}
...
}
};
main()
{
Call obj;
boost::thread th (boost::bind(&Call::func, &obj));
th.detach();
while(true) {
while (obj.flag == false);
...do something
}
}
// shared variables
boost::mutex mutex;
boost::condition_variable condition;
bool flag = false;
// signal completion
boost::unique_lock<boost::mutex> lock(mutex);
flag = true;
condition.notify_one();
// waiting in main method
boost::unique_lock<boost::mutex> lock(mutex);
while (!flag) {
condition.wait(lock);
}