Where to destroy thread and deadline_timer objects after timeout? - c++

my question is about a running deadline timers which wait for some operations represented by the same function to finish: But i dont't know, where to free my thread and deadline object after a safe finish oder an interrupt by deadline time out. When can that happen?
boost::asio::deadline_timer* mDeadline1;
boost::asio::deadline_timer* mDeadline2;
boost::thread* mThread1;
boost::thread* mThread2;
// start deadline timers
mDeadline1 = new boost::asio::deadline_timer(_io_service, boost::posix_time::seconds(2));
mDeadline1->async_wait(&MyClass::DeadlineTimedOut, this);
mDeadline2 = new boost::asio::deadline_timer(_io_service, boost::posix_time::seconds(2));
mDeadline2->async_wait(&MyClass::DeadlineTimedOut, this);
// Run operations in threads
mThread1 = new boost::thread(&MyClass::DoSomething, this);
mThread2 = new boost::thread(&MyClass::DoSomething, this);
// ...
void MyClass::DoSomething() {
// Do something time expensive and sleep, etc. for interrupt point ...
// which to cancel here!?
mDeadline->cancel();
delete mDeadline;
}
void MyClass::DeadlineTimedOut(const boost::system::error_code& pErrorCode) {
if(pErrorCode == 0) { // deadline timed out
// which to interrupt here?
mThread->interrupt();
}
if(pErrorCode == 995) { // deadline cancelled from outside
}
}
Has anyone some advice? Graceful, B.

The timers as they stand are meaningless - only you know what they mean and what they are supposed to do - so you have to decide what to cancel. As to cleaning up, hold them in a scoped_ptr or shared_ptr and they will be automagically cleaned up when the scope/last reference is done.

Related

Handle mutex lock in callback c++

I've got a Timer class that can run with both an initial time and an interval. There's an internal function internalQuit performs thread.join() before a thread is started again on the resetCallback. The thing is that each public function has it's own std::lock_guard on the mutex to prevent the data of being written. I'm now running into an issue that when using the callback to for example stop the timer in the callback, the mutex cannot be locked by stop(). I'm hoping to get some help on how to tackle this issue.
class Timer
{
public:
Timer(string_view identifier, Function &&timeoutHandler, Duration initTime, Duration intervalTime);
void start()
void stop() // for example
{
std::lock_guard lock{mutex};
running = false;
sleepCv.notify_all();
}
void setInitTime()
void setIntervalTime()
void resetCallback(Function &&timeoutHandler)
{
internalQuit();
{
std::lock_guard lock{mutex};
quit = false;
}
startTimerThread(std::forward<Function>(timeoutHandler));
}
private:
internalQuit() // performs thread join
{
{
std::lock_guard lock {mutex};
quit = true;
running = false;
sleepCv.notify_all();
}
thread.join();
}
mainLoop(Function &&timeoutHandler)
{
while(!quit)
{
std::unique_lock lock{mutex};
// wait for running with sleepCv.wait()
// handle initTimer with sleepCv.wait_until()
timeoutHandler(); // callback
// handle intervalTimer with sleepCv.wait_until()
timeoutHandler(); // callback
}
}
startTimerThread(Function &&timeoutHandler)
{
thread = std::thread([&, timeoutHandler = std::forward<Function>(timeoutHandler)](){
mainLoop(timeoutHandler);
});
}
std::thread thread{};
std::mutex mutex{};
std::condition_variable sleepCv{}
// initTime, intervalTime and some booleans for updating with sleepCv.notify_all();
}
For testing this, I have the following testcase in Gtest. I'm expecting the timer to stop in the callback. Unfortunately, the timer will hang on acquiring the mutex lock in the stop() function.
std::atomic<int> callbackCounter;
void timerCallback()
{
callbackCounter.fetch_add(1, std::memory_order_acq_rel);
}
TEST(timerTest, timerShouldStopWhenStoppedInNewCallback)
{
std::atomic<int> testCounter{0};
Timer<std::chrono::steady_clock > t{"timerstop", &timerCallback, std::chrono::milliseconds(0), std::chrono::milliseconds(100)};
t.resetCallback([&]{
testCounter += 1;
t.stop();
});
t.start();
sleepMilliSeconds(100);
ASSERT_EQ(testCounter.load(), 1); // trigger due to original interval timeout
sleepMilliSeconds(100);
ASSERT_EQ(testCounter.load(), 1); // no trigger, because stopped in new callback
}
Removing all the mutexes in each of the public fucntions, fixes the issue. But that could lead to possible race conditions for data being written to variables. Hence each function has a lock before writing to f.e. the booleans.
I've tried looking into the std::move functionality to move the thread during the resetCallback into a different variable and then call join on that one. I'm also investigating recursive_mutex but have no experience with using that.
void resetCallback(Function &&timeoutHandler)
{
internalQuit();
{
std::lock_guard lock{mutex};
quit = false;
}
auto prevThread = std::thread(std::move(this->thread));
// didn't know how to continue from here, requiring more selfstudy.
startTimerThread(std::forward<Function>(timeoutHandler));
}
It's a new subject for me, have worked with mutexes and timers before but with relatively simple stuff.
Thank you in advance.

condition_variable doesn't get notified to wake up even with a predicate

I'm having a problem where I'm having a few condition_variable's get stuck in their wait phase even though they've been notified. Each one even has a predicate that's being set just in case they miss the notify call from the main thread.
Here's the code:
unsigned int notifyCount = 10000;
std::atomic<int> threadCompletions = 0;
for (unsigned int i = 0; i < notifyCount; i++)
{
std::atomic<bool>* wakeUp = new std::atomic<bool>(false);
std::condition_variable* condition = new std::condition_variable();
// Worker thread //
std::thread([&, condition, wakeUp]()
{
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);
condition->wait(lock, [wakeUp] { return wakeUp->load(); });
threadCompletions++;
}).detach();
// Notify //
*wakeUp = true;
condition->notify_one();
}
Sleep(5000); // Sleep for 5 seconds just in case some threads are taking a while to finish executing
// Check how many threads finished (threadCompletions should be equal to notifyCount)
Unless I'm mistaken, after the for loop is done, threadCompletions should always be equal to notifyCount. Very often though, it is not.
When running in release, I'll sometimes get just one or two out of 10000 threads that never finished, but when running in debug, I'll get 20 or more.
I thought maybe the wait call in the thread is happening after the main thread's notify_one call (meaning it missed it's notification to wake up), so I passed a predicate into wait to insure that it doesn't get stuck waiting. But it still does in some cases.
Does anyone know why this is happening?
You are assuming the call to wait() is atomic. I don't believe it is. That is why it requires the use of a mutex and a lock.
Consider the following:
Main Thread. Child Thread
// This is your wait unrolled.
while (!wakeUp->load()) {
// This is atomic
// But already checked in the
// thread.
*wakeUp = true;
// Child has not yet called wait
// So this notify_one is wasted.
condition->notify_one();
// The previous call to notify_one
// is not recorded and thus the
// thread is now locked in this wait
// never to be let free.
wait(lock);
}
// Your race condition.
Calls to notify_one() and wait() should be controlled via the same mutext to make sure they don't overlap like this.
for (unsigned int i = 0; i < notifyCount; i++)
{
std::atomic<bool>* wakeUp = new std::atomic<bool>(false);
std::mutex* mutex = new std::mutex{};
std::condition_variable* condition = new std::condition_variable();
// Worker thread //
std::thread([&]()
{
std::unique_lock<std::mutex> lock(*mutex);
condition->wait(lock, [&wakeUp] { return wakeUp->load(); });
threadCompletions++;
}).detach();
// Notify //
*wakeUp = true;
std::unique_lock<std::mutex> lock(*mutex);
condition->notify_one();
}
// Don't forget to clean up the new structures correctly/.
You have data racing. Consider following scenario:
Worker Thread: condition variable tests for whether wakeup is true - it isn't
Main Thread: wakeup is set to true and condition variable is getting notified
Worker Thread: condition_variable triggers wait but it happens after notification already occurred - impling that notification misses and the thread might never wake up.
Normally, synchronization of condition variables is done via mutexes - atomics aren't too helpful here. In C++20 there will be special mechanism for waiting/notifying in atomics.

C++ Wait for bool to change in another class

I have a Program class and a Browser class.
Inside my Program::Run(), I launch the Browser to start in a separate thread.
However, before I continue with my Run() method, I want to wait for a certain part of the Browser to initialize, thus I need to check if a variable has been set in the browser object.
Used as the thread for the browser
int Program::_Thread_UI_Run() {
...
return Browser->Run();
}
I am using async to run the browser thread and retrieve its return value when it is finished.
int Program::Start() {
std::unique_lock<std::mutex> lck(mtx);
auto t1 = std::async(&Program::_Thread_Browser_Run, this);
cv.wait(lck);
... when wait is released, do stuff
// Thread finishes and returns an exit code for the program
auto res1 = f1.get();
// return res1 as exit code.
}
Browser.cpp class
int Browser::Run()
{
// Initialize many things
...
m_Running = true;
cv.notify_all(); // Notify the waiter back in Program
// This will run for as long as the program is running
while (m_Running)
{
... browser window message loop
}
return exit_code;
}
I have problems setting this up. The program is crashing :/
Do I pass the mutex variable to everything using it? Or just recreate it in every function body?
What about the conditional_variable?
With the current setup the program crashes:
The exception Breakpoint
A breakpoint has been reached.
(0x80000003) occured in the application at location 0x107d07d6.
Hints and help is appreciated
Edit: Updated code to match new suggestions
In browser's .h file: std::atomic_bool m_Running;
int Browser::Run(std::condition_variable& cv)
{
int exit_code = 0;
// Set up, and attain the desired state:
...
m_Running = true;
cv.notify_all();
while (m_Running)
{
// Process things etc
}
return exit_code;
}
int Program::Start()
{
std::mutex m;
std::condition_variable cv;
auto t1 = std::async(&Program::_Thread_UI_Run, this, std::ref(cv));
std::unique_lock<std::mutex> lock(m);
cv.wait(lock);
.... stuff
return t1.get();
}
I have a logger that helps me keep track of how the program is running.
By placing logger calls in crucial places in the code I was able to confirm that the program waits appropiately before continuing. However I still get prompted with
The exception Breakpoint A breakpoint has been reached. (0x80000003)
occured in the application at location 0x107d07d6.
By commenting out //cv.wait(lock); the program resumes to work.. :/
Why would waiting making it crash like that?
You definitely want to use std::condition_variable. It allows you to signal other threads once an operation has complete, so in your case, once the bool has been set:
Browser::Run()
{
// Set some things up, make sure everything is okay:
...
m_Running = true; // Now the thread is, by our standards, running*
// Let other threads know:
cv.notify_all();
// Continue to process thread:
while (m_Running)
{
}
}
And then in your main / other thread:
auto t1 = std::async(&Program::_Thread_Browser_Run, this);
// Wait until we know the thread is actually running. This will pause this thread indefinitely until the condition_variable signals.
cv.wait();
You should pass the std::condition_variable into any function using it, so your code would look more like:
int Browser::Run(std::condition_variable& cv)
{
int exit_code = 0;
// Set up, and attain the desired state:
...
m_Running = true;
cv.notify_all();
while (m_Running)
{
// Process things etc
}
return exit_code;
}
int Program::Start()
{
std::mutex m;
std::condition_variable cv;
auto t1 = std::async(&Program::_Thread_UI_Run, this, std::ref(cv));
std::unique_lock<std::mutex> lock(m);
// Wait until the browser is in the desired state
cv.wait(lock);
// The thread has signalled. At this point, Browser::m_Running = true
// Wait for the browser to exit, and then propagate its exit code
return t1.get();
}
#Richard Hodges raises an excellent point in the comments, which I overlooked: m_Running needs to be std::atomic (or have locking around its use) otherwise both threads may try to use it once. std::condition_variable is thread-safe and doesn't require locking around it.
*Of course the thread is running at that point, I just mean it's in the state you desire

Including a ping timeout feature

I have Server A that receive's updates from Server B. I would like to add functionality to Server A where if it does not receive a message(server B will send update and ping messages) in 1 minutes time, Server A will go into a paused state and wait for messages to come in again.
I was looking into a boost::asio::deadline_timer, but I cannot figure out if it is possible, or if you can run this asynchronously. I tried a class that runs in its own thread and uses a deadline timer, but I am unable to cancel and restart the deadline timer. Here is some example code I used for that.
The implementation:
void ping_timeout::reset_timer()
{
ping_timeout_.cancel();
ping_timeout_.expires_from_now(boost::posix_time::seconds(60));
//Call to clear the cache of a static class, which is the paused state I would like
ping_timeout_.async_wait(boost::bind(&cache::empty_cache));
io_.run();
}
I am unable to cancel the deadline timer from my main thread of execution by calling reset timer, I am guessing because io_.run() is waiting for the 60 seconds to expire.
Is there any modification I can do, any any libraries out there that I can us to achieve the results I would like? Any help would be appreciated.
Thank you
Edit:
Main Loop:
ping_timeout timeout;
boost::thread(boost::bind(&cache::run_io,boost::ref(service)));
while(true)
{
std::string message = s_recv(subscriber);
}
if(message.compare("UPDATE") == 0)
{
//Process update
}
else if(message.compare("PING") == 0)
{
timeout.reset_timer();
}
}
Edit 2:
Working code:
void cache::process_cache()
{
boost::asio::io_service service;
boost::asio::io_service::work work(service);
boost::thread(boost::bind(&cache::run_io,boost::ref(service)));
boost::asio::deadline_timer timer(service,boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache,boost::asio::placeholders::error));
while(true)
{
std::string message = s_recv(subscriber);
if(message.compare("UPDATE") == 0)
{
//Process update
}
else if(message.compare("PING") == 0)
{
timer.cancel();
timer.expires_from_now(boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache,boost::asio::placeholders::error));
}
}
}
void cache::empty_cache(const boost::system::error_code& e)
{
if(e.value() == 0)
{
//Clear cache
}
}
void cache::run_io(boost::asio::io_service& io)
{
io.run();
}
boost::asio::io_service::run() is a blocking call. In your specific case, you should avoid calling that in your main thread.
Note: In a typical async-driven app, you should build your app around the run method.
As for the timer code logic, something like that should work :
boost::asio::io_service service;
// Creates a work object to prevent the thread from exiting after the first job is done
boost::asio::io_service::work work(service);
// Creates the timer and post the aync wait now, will only start when service.run() is called
boost::asio::deadline_timer timer(service, boost::posix_time::seconds(60));
timer.async_wait(boost::bind(&cache::empty_cache, ...));
// Starts the worker thread to allow the timer to asynchronously waits
boost::thread ping_thread(boost::bind(&boost::asio::io_service::run, &service));
while (true) // you should add a condition in order to leave if the timer expires
{
std::string message = s_recv(subscriber);
/**/ if (message == "UPDATE")
{
// Process update
}
else if (message == "PING")
{
// Cancel the current timer
timer.cancel();
// Start another async wait
timer.async_wait(boost::bind(&cache::empty_cache, ...));
}
}

Qt QTimer is it safe to stop it this way?

Is it safe to stop Qt's timer in it's "timeout" signal/slot function?
Can't seem to find any information in Qt documentation about the QTimer.
I have created a timer that is periodically sending a "keep alive" messages to the server.
I want this timer to be stopped if there is some kind of error while sending my message.
private:
QTimer* mpKeepAliveTimer;
Timer is initialized like this:
mpKeepAliveTimer = new QTimer(/* this */);
QObject::connect(mpKeepAliveTimer, SIGNAL(timeout()), this, SLOT(OnKeepAlive()));
mpKeepAliveTimer->start(KEEP_ALIVE_PERIOD);
Stopped like this:
if (mpKeepAliveTimer != NULL) // <-- Edited
{
if (mpKeepAliveTimer->isActive() == true)
mpKeepAliveTimer->stop();
delete mpKeepAliveTimer;
mpKeepAliveTimer = NULL;
}
Timeout function looks like this:
void Classname::OnKeepAlive()
{
if (isErrorFound == true)
mpKeepAliveTimer->stop(); // <---- IS THIS SAFE?
}
Thanks.
As long as you are not explicitly using Queued Connections, this is safe.
This is because the emit timeout() function will not return until all the slots it's connected to were processed.
If you were however using Queued Connections, it could in theory happen that there are still unprocessed timeout events in the Event Queue, so to make it hyper-safe you could use the following:
void Classname::OnKeepAlive()
{
if (!mpKeepAliveTimer || !mpKeepAliveTimer->isActive()) return;
if (isErrorFound)
{
mpKeepAliveTimer->stop();
}
}
Note that the condition in your stop function should be != NULL instead of == NULL. You can also write that function as follows, however:
if (mpKeepAliveTimer)
{
delete mpKeepAliveTimer;
mpKeepAliveTimer = NULL;
}
As already suggested in the comments, QTimer will stop itself in its destructor.