Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
kloffy
Can someone post an example for this?
You will need an object that will do the polling:
Code:
{
Q_OBJECT
public:
Poller();
~Poller();
public slots:
void poll();
void stop();
private:
};
Poller::Poller()
{
// open the device
connect( &timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
timer.start( 100 ); // wait at least 100 ms between polling
}
Now all you have to do is to create such Poller object in your thread. Note that if this is the only object that lives in that thread, it will be always "idle".
Quote:
Originally Posted by
kloffy
What are the " sophisticated idle processing schemes"?
You can pass some flags to processEvents() to control what events should be processed.
Re: QThread and QEventLoop - Idle Processing
Thank you! That was exactly what I was looking for. It just so happens that I stumbled upon a similar example right before I saw your post. It had suspend function to stop the timer, which is pretty neat. If anyone's interested:
Code:
class MyThreadObject
: public QObject {
MyThreadObject() {
connect( &myTimer, timeout(), this, onTimeOut());
}
slot onSuspendThread() {
myTimer.stop();
}
slot onResumeThread() {
myTimer.start(0);
}
private slot onTimeOut() {
// do a few comutation steps.
// Should return "quickly" to the event loop
}
}
slot MyThread:run() {
MyThreadObject threadObject; //=> the threadObject affinity is the thread
// here, connect the appropriate signals to the appropriate slots
threadObject.onResumeThread();
exec();
}
}
Re: QThread and QEventLoop - Idle Processing
I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:
Code:
void Thread::run() {
while(!finished){
poll();
}
}
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
wysota
I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread.
Yes, but if I understood correctly then it wouldn't be possible to connect signals/slots with objects in other threads. (Using queued connections)
Re: QThread and QEventLoop - Idle Processing
It would be possible. You could emit signals but you couldn't have queued slots. If you have a single object that only polls for data, you don't need slots, so...
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
wysota
I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:
Code:
void Thread::run() {
while(!finished){
poll();
}
}
This was my first approach to a similar problem. But, what would be the best way to stop the thread then?
Since I want to terminate the thread from "outside", I guess that would be to set the finished variable to true and then call wait(). But then again the finished variable will be accessed from two different threads and need to be protected by a Mutex?
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
Mhondoz
This was my first approach to a similar problem. But, what would be the best way to stop the thread then?
Set the "finished" flag to true.
Quote:
But then again the finished variable will be accessed from two different threads and need to be protected by a Mutex?
No, it doesn't, because only one thread may change the flag. The worst that may happen is that the thread will perform once cycle more, which is completely ignorable.
Re: QThread and QEventLoop - Idle Processing
Ok, thanks. :-)
So if I understand correctly, this will work and is thread safe:
mythread.h
Code:
public:
~MyThread();
protected:
void run();
private:
bool _bFinished;
};
mythread.cpp
Code:
MyThread
::MyThread(QObject *parent
) : QThread(parent
), _bFinished
( false ) {
start();
}
MyThread::~MyThread() {
_bFinished = true;
wait();
}
void MyThread::run() {
while ( ! _bFinished ) {
// Do something
}
}
What I want to accomplish here is to have the thread start when it is constructed, and stop the thread in the destructor. My concern was the _bFinished variable which I believe is accessed by the MyThread thread in the while loop in run(), but in the destructor it will be accessed by the thread that constructed MyThread, for example the main thread...
Re: QThread and QEventLoop - Idle Processing
It doesn't matter as nothing tries to set _bFinished to false when it's true. And that's the only case when a newly set value could be overwritten with a different value. If you are not sure about it, use QAtomicInt (available since 4.4, so the link is invalid at the time of writing this post).
Re: QThread and QEventLoop - Idle Processing
That makes sense. Thank you very much. :-)
Re: QThread and QEventLoop - Idle Processing
I all,
Quote:
Originally Posted by
wysota
I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:
Code:
void Thread::run() {
while(!finished){
poll();
}
}
In that case, the polling will happen every 100ms, not doing idle processing. To perform idle processing, a timer with 0 timeout and an event loop are mandatory. Am I correct?
Thanks
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
jlemaitre
In that case, the polling will happen every 100ms and the event loop is mandatory to perform idle processing. Am I correct?
Sleep and event loops don't go together well. If you want to do idle processing in the thread besides the main task the thread is doing, use a timer instead of sleep().
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
wysota
If you want to do idle processing in the thread besides the main task the thread is doing, use a timer instead of sleep().
In the initial post of the op, I understood the idle processing is the main task. (Polling the device is the only task of the thread, and it must be done at idle time.) In that case, is its timer-based solution (re-coded below) appropriate?
Code:
class DevicePoller
: public QThread{
Q_OBJECT
slots:
void poll();
protected:
virtual void run()
{
connect( m_timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
m_timer.start( 0 );
exec();
}
};
Or, is it best to avoid timers at all, and launch a thread with QThread::IdlePriority:
Code:
class DevicePoller
: public QThread{
protected:
virtual void run()
{
while( !finished ) poll();
}
};
DevicePoller mythread;
mythread.
start( QThread::IdlePriority );
// ...
Or, am I wrong and there is another strategy?
Thanks for the rapid answer anyway!
Re: QThread and QEventLoop - Idle Processing
Quote:
Originally Posted by
jlemaitre
In the initial post of the op, I understood the idle processing is the main task. (Polling the device is the only task of the thread, and it must be done at idle time.) In that case, is its timer-based solution (re-coded below) appropriate?
It's a periodic task, not idle processing.
Quote:
Code:
class DevicePoller
: public QThread{
Q_OBJECT
slots:
void poll();
protected:
virtual void run()
{
connect( m_timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
m_timer.start( 0 );
exec();
}
};
There is no point in using threads here, you can use the main thread with this approach.
Quote:
Or, is it best to avoid timers at all, and launch a thread with QThread::IdlePriority:
Code:
class DevicePoller
: public QThread{
protected:
virtual void run()
{
while( !finished ) poll();
}
};
DevicePoller mythread;
mythread.
start( QThread::IdlePriority );
// ...
Or, am I wrong and there is another strategy?
Thread priorities are just hints for the OS, it may ignore them so that's not a good approach -- you'll end up with a busy loop.