What exactly happens with QTimer start function? - c++

I have the following code:
mytimer.cpp
#include "mytimer.h"
#include <QtCore>
MyTimer::MyTimer()
{
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
timer->start(1000);
}
void MyTimer::mySlot()
{
qDebug()<<"timer executed";
}
and in the main.cpp
#include <QCoreApplication>
#include "mytimer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyTimer mtimer;
qDebug()<<"DONE";
return a.exec();
}
Now the output comes as:
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
I am really confused by this. How is that we are done with our main function and still the code for the SLOT mySlot() is getting executed?
What are the important aspects to this? that I need to understand?
Also what changes occurs when I modify mytimer.cpp MyTimer() to:
MyTimer::MyTimer()
{
timer = new QTimer(this);
QEventLoop eventloop;
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
connect(timer,SIGNAL(timeout()),&eventloop,SLOT(quit()));
timer->start(1000);
eventloop.exec();
}
There is one timer executed just before DONE is printed. To Be specific the output now becomes:
timer executed
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
What caused that separate timer executed to appear above the DONE?

No - your main function is not done. It called a.exec() which will never return in your application.
a.exec() in turn processes a "message queue" which triggers all the timer events that call mySlot().

a.exec starts the event loop. It doesn't return a value until either QApplication::exit() or QApplication::quit() or all windows are closed.

What caused that separate timer executed to appear above the DONE?
The timer signals are always emitted from within the outermost event loop - because that's where the locus of control is (i.e. that's where the thread is running - it's inside Qt). Since you spun a local event loop (eventloop.exec();), that's where the timer invocation came from. As soon as that event loop was done and that exec() had returned, the MyTimer constructor had exited, DONE was printed out, and remaining timer invocations happen from the main event loop.
Generally speaking, code that nests event loops is broken, so if you ever find yourself with more than one exec() on the call stack, you're doing it wrong. There are a few notable exceptions: native dialogs on OS X require their own nested event loop due to OS X API deficiencies, and QDrag requires exec() also most likely due to platform deficiencies that require an exec() for portability, even if on some platforms it'd be unnecessary.

Related

Make something happen after 5 minutes has passed, while other code still runs in C++

I am trying to make a timer, so after five minutes something happens. The catch is that while the timer is being checked constantly I need other code to be running. I have created a sample below, of how the actually code looks, the function with the timer is in class, so I did the same thing below. Here is the code:
This code assumes all necessary headers are included
Class.h:
class MyClass
{
public:
void TimerFunc(int MSeconds);
};
void MyClass::TimerFunc(int MSeconds)
{
Sleep(MSeconds); //Windows.h
//Event code
return;
}
Main.cpp:
int main()
{
MyClass myClass;
myClass.TimerFunc(300); //300 is 5 minutes
//Here we do not want to wait for the five minutes to pass,
//instead we want to continue the rest of the code and check
//for user input as below
std::cout << "This should print before the Event Code happens.";
}
The problem here is that the code waits for the five minutes to pass, and then continues. I'm not sure if threading would be a good option here, I haven't done much with it before, if anyone could help me with that, or knows a better way to go about it, any help is appreciated.
If you don't mind your Event executing in a different thread-context, you could have your Timer class spawn a thread to do the waiting and then the event-execution; or (on POSIX OS's) set up a SIGALRM signal and have the signal handler do the Event. The downside of that is that if your event-code does anything non-trivial, you'll need to worry about race conditions with the concurrently executing main thread.
The other approach is to have your main thread check the clock every so often, and if the time-to-execute has passed, have your main thread call your Event routine at that time. That has the advantage of automatic thread-safety, but the disadvantage is that you'll have to add that code into your thread's main event loop; you can't easily hide it away inside a class like the one in your example.
With C++11 threads, this would work like this:
int main()
{
MyClass myClass;
thread ti([](MyClass &m){m.TimerFunc(300); }, ref(myClass)); // create and launch thread
// ... code executed concurrently to threaded code
ti.join(); // wait for the thread to end (or you'll crash !!)
}
Add a private member to your class:
atomic<bool> run=true; // designed to avoid race issue with concurrent access
Update its timer function to loop while this variable is true:
void MyClass::TimerFunc(int MSeconds)
{
while (run) {
this_thread::sleep_for(chrono::milliseconds(MSeconds)); // standard sleep instead of microsoft's one
//Event code
}
return;
}
Foresee within the class a member function to stop the threaded loop:
void Stop() {
run = false;
}
Finally update main() to call myClass.Stop() when the timer function is no longer needed (i.e. before calling ti.join() )
EDIT: attention, nasty error to avoid: be careful to refer to ref(myClass) in the thread constructor. If you would forget this, the thread ti would use a reference to a copy of myClass instead of the original object.

Start QTimer from another non-gui thread

I try to start QTimer from another thread ( to get better accuracy ).
I think that problem is with function connect but let see my code:
//code from constructor of parent.cpp class
{
//run_clock_timer(this); // this works
std::thread t1{ [this] { run_clock_timer(this); } }; //not works
t1.join();
}
And function:
void class::run_clock_timer(class* inst){
QTimer * test = new QTimer(inst);
connect(test, SIGNAL(timeout()), inst, SLOT(updateTime()));
test->setInterval(50);
test->start(timer_precision);
}
Debugger told me that code from run_clock_timer was run, but no result.
I think i will do it with no problem when i use QThread, but i want to use std::thread.
So whats wrong with my function ?
The problem is that QTimer depends on the ability to interact with a running Qt event loop in order to perform its task. Since a non-Qt thread has no event loop, the QTimer can't do its job. (i.e. there has to be some Qt code running in the thread, that will emit the timeout() signal, that doesn't just happen on its own)

std::thread consumes all CPUs in Qt

I have a function. In my function there is a c++ thread & a Qtimer. By c++ thread I receive ARP Reply packets & by QTimer I send ARP Request packets.
The simplified structure:
int foo()
{
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
std::thread tCapture(Capture);
tCapture.join();
return 0;
}
void Capture()
{
while ( ! finishCapturing )
{
do sth
}
}
In the tCapture thread I have a while loop that consumes all CPUs & the Qtimer does not work!
I use .join() because I want to wait for the thread to finish.
when I set finishCapturing flag in Qtimer slot, the thread will be finished.
The above codes don't work correctly, because the c++ thread consumes all CPUs!
what is the problem?
Thanks a lot.
Ya Ali.
The problem is joining the thread right after creating them, that blocks the GUI thread and the QTimer and all slots on that thread.
What you should do is emit a signal when capturing is done;
public void beginSending(){
//do sending and capture
finishCapturing =true;
emit finshedCapture();
}
If needed you can put the body of the while in a slot and have it called repeatedly with a QTimer with a timeout of 0 (which means the slot will get called as often as possible).
then you can connect the finshedCapture() signal to the stop() slot of the QTimer
int foo()
{
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
QTimer* timer = new QTimer(this);
connect(timer, signal(timeout()), this, slot(Capture()));
connect(this, signal(finshedCapture()), timer, slot(stop()));
connect(this, signal(finshedCapture()), timer, slot(deleteLater()));//cleaup when done
timer->setTimeout(0);
timer->setSingleShot(false);
timer->start();
return 0;
}
void Capture()
{
//no while because the timer will call it as needed
//do sth
}
Without seeing more of the code, this is guess-work:
1: Capture() does not block, so will consume as much CPU time as the operating system gives it - which will be 100% of one CPU on a lightly loaded multi-core system.
2: foo() is called on the main thread. It then attempts to join() with the your thread - which blocks until the thread finished. I see nothing setting finishCapturing, so it doesn't.
3: The QTimer is dispatched through the run-loop - which is blocked.
In effect, this is deadlock of the main thread.

Qt: QFuture/QtConcurrent timeout function call

I need a timeout function call. I work mainly with Qt (4.7.3, 4.8.5) and so i tried to find a solution with Qt. The two classes QFuture and QtConcurrent seems to do 99% of what i need but i can not find a possibility to timeout a function call.
My Problem:
I have my tester (gtest) and i test a function which can end in an infinity loop => so i want to test this to fix that problem[s] (this function is internal extrem complex :-( ). I want to add a timeout-time to break out if there is an infinity loop => so i can tell the tester that something is wrong (infinity loop) and i will terminate the thread.
I have search for something like that:
QtConcurrent::run(............,30000 /*30 seconds timeout)*/;
Does anybody know how i can do this?
(If it is possible with native C++, or boost, or ... you can also tell me your solution)
I was focusing on the QtConcurrent module, since you mentioned it in your question. But you can achieve your goal also with plain QThread:
// A Thread calling your test function
class MyThread : public QThread {
protected:
void run() { myFunction(); }
};
// calling the function
MyThread t;
t.start();
if ( t.wait(30000) ) {
// Finished
} else {
// Not finished
// ATTENTION: USE TERMINATE WITH CARE (see QThread documentation)!
t.terminate();
}
The call to terminate will forceably stop the thread and thus stop the execution of your function. Note however that the thread cannot cleanup, and any resources used by your function are not freed properly.
Old Answer:
You can do this with Qt, using a QFutureWatcher, a QTimer, and a helper QEventLoop . Setup your concurrent run, and watch the result with the watcher. Set the Timout with the timer, and wait until either is finished, in a Event loop.
// Setup eventloop, watcher and timer
QEventLoop loop;
QFutureWatcher watcher;
QObject::connect( &watcher, SIGNAL(finished()), &loop, SLOT(quit()));
QTimer::singleShot( 30000, &loop, SLOT(quit()) );
// Start function call
QFuture<T> future = QtConcurrent::run(...);
// Watch the call
watcher.setFuture( future );
// Wait until event loop finishes
loop.exec();
// Now either future has finished, or timeout was reached...
if ( future.isFinished() ) {
// Function completed!
} else {
future.cancel();
// Infinite loop...
}
The issue is that you cannot safely terminate a thread without thread's cooperation. The thread may be accessing some shared data structure, like the C-runtime heap, and if it is terminated forcefully then such data structures will remain in a mid-change state, essentially corrupted. Any future access to them from within the program will likely cause a crash or worse.
The case of an infinite loop is not by any means different from other bad scenarios. What if the function you launch crashes the program, how do you report it to the tester?
In your case you simply don't trust the code that you're executing. The solution is to launch it in a separate process, whose safe termination is guaranteed by the operating system. By isolating the tested code from the tester application you guarantee that you can detect all kind of problems, including timeouts or abnormal termination.
I think you need to find out why the infinite loop happens rather than trying to fix symptoms.
QtConcurrent::run() uses thread pool to run tasks. You can't safely terminate thread, so the only way to safely finish a task is to return from it.
If you still want timeouts, you can add something like this to your function with loop:
QTime t;
t.start();
// it's your loop
while( true ) {
if( t.elapsed() > 30*1000 ) {
return 1;
}
...
}
You can bind a QTimer signal to the slot:
auto process = QtConcurrent::run(...);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &process]() {
process.cancel();
});
timer->start(3000);
Edit: As the cancel() method won't work on the QtConcurrent::run function, the easiest thing would be to use some kind of isRunning flag:
bool isRunning = true;
void runnable() {
while (isRunning) {
...
}
}
auto process = QtConcurrent::run(runnable);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &isRunning]() {
isRunning = false;
});
timer->start(3000);

How can I protect a QThread function so it will not be called again until finished its previous work?

I'm using a QThread and inside its run method I have a timer invoking a function that performs some heavy actions that take some time. Usually more than the interval that triggers the timer (but not always).
What I need is to protect this method so it can be invoked only if it has completed its previous job.
Here is the code:
NotificationThread::NotificationThread(QObject *parent)
: QThread(parent),
bWorking(false),
m_timerInterval(0)
{
}
NotificationThread::~NotificationThread()
{
;
}
void NotificationThread::fire()
{
if (!bWorking)
{
m_mutex.lock(); // <-- This is not protection the GetUpdateTime method from invoking over and over.
bWorking = true;
int size = groupsMarkedForUpdate.size();
if (MyApp::getInstance()->GetUpdateTime(batchVectorResult))
{
bWorking = false;
emit UpdateNotifications();
}
m_mutex.unlock();
}
}
void NotificationThread::run()
{
m_NotificationTimer = new QTimer();
connect(m_NotificationTimer,
SIGNAL(timeout()),
this,
SLOT(fire(),
Qt::DirectConnection));
int interval = val.toInt();
m_NotificationTimer->setInterval(3000);
m_NotificationTimer->start();
QThread::exec();
}
// This method is invoked from the main class
void NotificationThread::Execute(const QStringList batchReqList)
{
m_batchReqList = batchReqList;
start();
}
You could always have a thread that needs to run the method connected to an onDone signal that alerts all subscribers that it is complete. Then you should not run into the problems associated with double lock check and memory reordering. Maintain the run state in each thread.
I'm assuming you want to protect your thread from calls from another thread. Am I right? If yes, then..
This is what QMutex is for. QMutex gives you an interface to "lock" the thread until it is "unlocked", thus serializing access to the thread. You can choose to unlock the thread until it is done doing its work. But use it at your own risk. QMutex presents its own problems when used incorrectly. Refer to the documentation for more information on this.
But there are many more ways to solve your problem, like for example, #Beached suggests a simpler way to solve the problem; your instance of QThread would emit a signal if it's done. Or better yet, make a bool isDone inside your thread which would then be true if it's done, or false if it's not. If ever it's true then it's safe to call the method. But make sure you do not manipulate isDone outside the thread that owns it. I suggest you only manipulate isDone inside your QThread.
Here's the class documentation: link
LOL, I seriously misinterpreted your question. Sorry. It seems you've already done my second suggestion with bWorking.