Results 1 to 19 of 19

Thread: Advise sought on QEventLoop behavior

  1. #1
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Advise sought on QEventLoop behavior

    I have a strange case where the pair of entry/exit calls works fine when breakpoint is set, but does not if there is no breakpoint. (all in debug mode).

    I have QRunnable-derived class which also inherits from QEventLoop.
    In the "run" method I call exec() and then, after some processing, the event is posted into this instance that calls "exit" in event() function.

    Everything works if the breakpoint is set on "exit" call, I mean the event loop exits processing. However, without the breakpoint set, the eventloop never exits, even though the exit event is processed.

    My event method is:

    Qt Code:
    1. bool DataSourceProcess::event(QEvent* event)
    2. {
    3. if (event->type() == csvEvent::type())
    4. {
    5. std::ofstream f ("c:\\test\\test.Text");
    6. f <<"exit";
    7. f.close();
    8. exit ();
    9. }
    10. return QObject::event(event);
    11. }
    To copy to clipboard, switch view to plain text mode 

    I tried to use "wakeUp()" call prior to "exit()" with no effect. With breakpoin set on exit - everything works. Without breakpoint the eventloop never exits.

    I'll appreciate any advise or help in solving this problem (Qt 4.7.3, VS2010)

  2. #2
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Advise sought on QEventLoop behavior

    How do you call run(), I mean do use thread pool or as a regular bock and wait call ?

  3. #3
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    run method with details omitted for clarity.

    Qt Code:
    1. void DataSourceProcess::run()
    2. {
    3. res = addNewItems (); //addnewitem posts progress into this instance event loop, which in turn calls "exit()" as shown in the prevous post
    4. if (res)
    5. {
    6. emit onProgress("Entering event loop");
    7. exec();
    8. emit onProgress("Exited from event loop");
    9. }
    10.  
    11. emit onProgress("cleanup")
    12. if (_parent != NULL)
    13. {
    14. _sm->acquire(1);
    15. if (_sm->available() == 0)
    16. _parent->exit();
    17. }
    18. }
    To copy to clipboard, switch view to plain text mode 

    Class declaration:
    Qt Code:
    1. class DataSourceProcess : public QEventLoop, public QRunnable, public boost::noncopyable
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Ok, but how do you actually execute the runnable? And why do you inherit QEventLoop? To me it seems you'd be better with using QThread.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    Qt Code:
    1. void DataManager::launchDataProcess(const configDS& ds)
    2. {
    3. DataSourceProcess* dsp = new DataSourceProcess(ds, _dmcenter);
    4. connect(dsp, SIGNAL(onProgress (QString)), this, SLOT(onProgressUpdate(QString)) );
    5. connect(dsp, SIGNAL(onComplete (DataSourceProcess*)), this, SLOT(onProgressComplete(DataSourceProcess*)) );
    6. _processes.push_back(dsp);
    7. QThreadPool::globalInstance()->start(dsp);
    8. }
    To copy to clipboard, switch view to plain text mode 

    I agree, QThread seems to be better, but this is an existing code. The issue shows up after new requirements were implemented on top of it. And I'd like to understand what's going on with QRunnable and QEventLoop.


    Added after 1 19 minutes:


    unsuccessfull test:

    I've tried to isolate the issue with this simple use case. It implements console app with two methods of using QRunnable+QEventLoop: with events and with signal/slots.

    Both exibit the same problem with posting events.
    Attached Files Attached Files
    Last edited by TorAn; 8th June 2011 at 13:06.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Does the runnable get executed at all? Did it occur to you that blocking a runnable with a semaphore on a single core machine means you're exhausting the thread pool and no other concurrent tasks can run until the one blocked wakes up and finishes its task? Not that the block with acquiring the semaphore makes ANY sense...
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    Wysota,

    First of all, thank you for reviewing the case.

    Following are the answers, based not on the example code that I posted here, but on the actual code that lead me to ask my question.

    1. Does the runnable get executed at all?
    Yes, it does. I spend quite some time debugging the code and if it would not run I'd notice it well before wasting qtcenter.com user's time posting my question

    Main() starts a thread with run() method as:

    Qt Code:
    1. void myThread::run()
    2. {
    3.  
    4. while(QCoreApplication::startingUp ())
    5. sleep(1000);
    6.  
    7.  
    8. int inuse = 0;
    9. for (configOptions::container::const_iterator it = _options.datasources().begin(); it != _options.datasources().end(); ++it)
    10. if (it->isUsable())
    11. ++inuse;
    12.  
    13. if (inuse == 0)
    14. return;
    15.  
    16.  
    17. QSemaphore sm(inuse);
    18.  
    19. for (configOptions::container::const_iterator it = _options.datasources().begin(); it != _options.datasources().end(); ++it)
    20. if (it->isUsable())
    21. {
    22. DataSourceProcess* dsp = new DataSourceProcess(*it, drh, this, &sm);
    23. QThreadPool::globalInstance()->start(dsp);
    24. }
    25.  
    26. exec();
    27. qApp->exit(0);
    28. }
    To copy to clipboard, switch view to plain text mode 

    2. Did it occur to you that blocking a runnable with a semaphore on a single core machine means you're exhausting the thread pool and no other concurrent tasks can run until the one blocked wakes up and finishes its task?
    No, it did not, at least not in my case. QRunnable instances in QThreadPool are not blocked when one of these instances calls QSemaphore->acquire (1)? In my case QSemaphore instance is created with the number of resources equal to the number of QRunnable instances and is used as a counter for exiting the parent thread's event loop when all QRunnable instances are done working.

    QRunnable instance run method ends with:
    Qt Code:
    1. {
    2. ...
    3. if (_parent != NULL) // parent thread
    4. {
    5. _sm->acquire(1); // decrease number of available resources
    6. if (_sm->available() == 0) // when nothing is available
    7. _parent->exit(); // exit event loop of parent thread
    8. }
    9. }
    To copy to clipboard, switch view to plain text mode 
    3. Not that the block with acquiring the semaphore makes ANY sense...
    I don't create any blockage in my case. Parent thread starts event loop and need to exit it when all QRunnable processes are done working. I'll appreciate it if you can suggest a better approach.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Quote Originally Posted by TorAn View Post
    I don't create any blockage in my case. Parent thread starts event loop and need to exit it when all QRunnable processes are done working. I'll appreciate it if you can suggest a better approach.
    Qt Code:
    1. void func(type1 param1, type2 param2, ...) {
    2. // implement your runnable code here or call some other class/method
    3. }
    4. void Thr::run() {
    5. QFutureSynchronizer<void> sync;
    6. for(int i=0;i<...;++i){
    7. sync.addFuture(QtConcurrent::run(func, param1, param2,...));
    8. }
    9. // QFutureSynchronizer waits for all threads to finish
    10. }
    To copy to clipboard, switch view to plain text mode 
    "Thr" doesn't need an event loop. Actually the whole thread is not needed for anything at all, you can have the same logic without it, for instance:
    Qt Code:
    1. Result func(const Data &data) {
    2. // implement your logic here
    3. }
    4.  
    5. void MainThread::someFunc() {
    6.  
    7. QList<Data> data;
    8. data << Data(...);
    9. data << Data(...);
    10. data << Data(...);
    11. data << Data(...);
    12. QFutureWatcher<Result> *watcher = new QFutureWatcher<Result>(this);
    13. connect(watcher, SIGNAL(finished()), SLOT(processingDone()));
    14. QFuture<Result> future = QtConcurrent::mapped(data, func);
    15. watcher->setFuture(future);
    16. }
    To copy to clipboard, switch view to plain text mode 

    As for your original code -- you can't call parent thread's exit() method from within a different thread. The semaphore thingy also makes no sense, a simple QAtomicInt would do. Better yet, you should exit the event loop from the actual thread when all work is done.

    Furthermore from what I see you exit the application immediately after the work is done, so you might as well use blockingMapped() (or even blockingMapReduced() to write results to the file as they come) in my QtConcurrent code and forget about the future watcher.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. The following user says thank you to wysota for this useful post:

    TorAn (8th June 2011)

  10. #9
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    I have completed the use case sample with the QThread-derived class. It works as expected. It is even more interesting in respect to 2008 discussion here, where the responder is Thiago Macieira from Nokia. It essentially states that combination of QRunnable and QEventLoop provides the same functionality as QThread. I don't think that it is based on the sample code.

    I'll be very interested to hear comments.

    Wysota:

    Your last code snipped is very elegant. I did not use these classes at all in my practice. Thank you very much for your review.
    Attached Files Attached Files
    Last edited by TorAn; 8th June 2011 at 15:45.

  11. #10
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Advise sought on QEventLoop behavior

    Quote Originally Posted by Santosh Reddy
    How do you call run(), I mean do use thread pool or as a regular bock and wait call ?
    You did not answer this. How and where do you call run()?

  12. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    He did answer that, in post #5, line 7.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  13. #12
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    Per Wysota's example of the QConcurrent-based solution I am now looking at QFuture usage. I don't understand how to implement following scenario using this framework.

    My application processes various data files and submits it to the website for storage. Each data file comes from a separate provider. So, in respect to QConcurrent, I can describe operation for data processing using functor that I can pass to QtConcurrent::map. But this instance has to make multiple requests to the website via webservice, wait for the response and then decide what to do next - either stop or continue to send data until it finishes. If more data is available it makes another request to send data and so on.

    So, within this function object I have to implement waiting mechanism. Is my scenario a good candidate for QConcurrent or I should stick with direct threads?

  14. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Why do you want threads there at all? You can do all that in a single thread.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  15. #14
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    There is more to the use case that make threading a right choice. What I don't understand is if QtConcurrent provieds support beyond the sequential tasks.

  16. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Quote Originally Posted by TorAn View Post
    There is more to the use case that make threading a right choice.
    Name one thing, please.
    What I don't understand is if QtConcurrent provieds support beyond the sequential tasks.
    QtConcurrent doesn't care about the nature of tasks it executes.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  17. #16
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    For example, data acquisition processes for individual datasources can take from 3 min to 2 hours, depending on the datasource. There around 10 datasources that have to be processed, starting at the same time.

    I understand that QtConcurrent can process any task. But when the task that is processed is event or signal driven I have to organize it in the task instance and that brings back eventloop into the task.

  18. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Quote Originally Posted by TorAn View Post
    For example, data acquisition processes for individual datasources can take from 3 min to 2 hours, depending on the datasource. There around 10 datasources that have to be processed, starting at the same time.
    So why is it useful to do it in threads? All your threads will be doing most of the time is waiting for data to flow in. One thread is enough to handle all that without any effort.

    I understand that QtConcurrent can process any task. But when the task that is processed is event or signal driven I have to organize it in the task instance and that brings back eventloop into the task.
    Obviously, if you need events, you need an event loop. But you don't need an event loop for signals.

    If I understand correctly what you are trying to do, then you are way overcomplicating things. The best strategy is to acquire the data from network (or whatever outside source you're using) in a single thread for all the sources and then process the data using QtConcurrent. This gives you the simplest and the most efficient code.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  19. #18
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advise sought on QEventLoop behavior

    Wysota,

    I very much appreciate your review. I agree with the approach you suggested, part of it is actually implemented in the production code. Network communication is shared between threads, only data processing happends individually in a separate threads. All the reasons to keep it that way are relatively weak and I should redo the implementation using one thread for network and another for data processing.

    Per the results of my use case sample I already made the transition from QRunnable/QEventLoop to QThread. It required a miniscule change and everything works now as expected. However, in the next round of development I will make the next transition, from separate QThreads to one QThread and QConcurrent maps.

    Your advise and support is very helpful, thanks again.

  20. #19
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advise sought on QEventLoop behavior

    Quote Originally Posted by TorAn View Post
    However, in the next round of development I will make the next transition, from separate QThreads to one QThread and QConcurrent maps.
    No, no QThread. The main thread will do just fine, you don't need an extra thread for networking.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  21. The following user says thank you to wysota for this useful post:

    TorAn (9th June 2011)

Similar Threads

  1. Advise sought on working with binary files across OSes
    By TorAn in forum General Programming
    Replies: 2
    Last Post: 19th September 2010, 06:44
  2. Replies: 4
    Last Post: 1st June 2010, 11:42
  3. static QEventLoop strange behavior
    By SABROG in forum Qt Programming
    Replies: 2
    Last Post: 29th July 2009, 12:04
  4. advise sought on TreeView model design
    By QPlace in forum Qt Programming
    Replies: 0
    Last Post: 25th June 2009, 14:36
  5. Replies: 6
    Last Post: 25th February 2008, 21:18

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.