Results 1 to 14 of 14

Thread: QCoreApplication + event looping

  1. #1
    Join Date
    Feb 2006
    Posts
    91
    Thanks
    4
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default QCoreApplication + event looping

    I'm a bit confused about the way we should be using QCoreApplication::exec() for event looping. Here is how I understand the concept in terms of QApplication
    Qt Code:
    1. int main(int argc,char** argv)
    2. {
    3. QApplication app(argc, argv);
    4. QWidget wgt;
    5. wgt.show();
    6. return app.exec();
    7. }
    To copy to clipboard, switch view to plain text mode 
    Here, wgt.show() is a non-blocking function and app.exec() is executed right after wgt.show() executes. Which means that everything works fine and we can use click button or other events that are emitted by the widget because app.exec() has already been executed and event looping can be processed.

    How does this work in case of QCoreApplication ?
    For example
    Qt Code:
    1. int main(int argc,char** argv)
    2. {
    3. QCoreApplication app(argc, argv);
    4. MyClass obj;
    5. QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()),Qt::QueuedConnection);
    6. obj.ProcessSomething();
    7. return app.exec();
    8. }
    To copy to clipboard, switch view to plain text mode 

    Here, ProcessSomething() does a lot of things including emitting signals and assigning them to slots. However, those signals are emitted from QProcess and other Qt Objects won't work since app.exec() has not been executed. My question is how to create a non-blocking function in case of console application where we are not waiting for user input. If we move app.exec() above processing, then the application will halt.
    The problem here is that there is no GUI that will wait for user action on objects, I've to somehow initiate the event looping before doing the processing and I don't know how ?
    Humans make mistake because there is really NO patch for HUMAN STUPIDITY

  2. #2
    Join Date
    Apr 2011
    Posts
    124
    Thanks
    1
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows Symbian S60

    Default Re: QCoreApplication + event looping

    If the system doesn't prevent it (because you lock out the UI for too long), you can do as much as you want in sequential logic before you get to the exec(). However, not until you get to exec() (or to a processEvents() call) are many of the events and signals handled, so any of your logic that depends on them will be broken.

    You can insert your own processEvents() calls at appropriate points in your code, to let the event/signal handling occur, and if done judiciously this will permit sequential logic to operate while using events/signals, but it's meaningless to say you could "initiate event looping", since that's not an asyncronous activity but rather a literal loop inside exec().

    Another choice is to construct your sequential logic using a state machine, so that each "atomic" operation triggers the next through event or signal. Sometimes this is actually an effective approach, allowing pseudo-parallel processing techniques, etc, and sometimes it's at least an interesting intellectual exercise. But mostly it's a drag.

    You can of course stick sequential logic in a separate thread, to allow it to execute in parallel with the UI, but then it will not be able to interact with the UI or use events/signals.

  3. #3
    Join Date
    Feb 2006
    Posts
    91
    Thanks
    4
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QCoreApplication + event looping

    Well it works now. I was just emitting the done() SIGNAL before the QProcess finished its command. But now the question is how are the signal/slots of QProcess working here as app.exec() has not been executed yet and we are still inside ProcessSomething(). Is it due to the fact that until the QProcess executes its command app.exec() has been executed ? Or am I totally missing something here ? Also is there a nice way to do this ?
    Last edited by ct; 28th May 2011 at 05:53.
    Humans make mistake because there is really NO patch for HUMAN STUPIDITY

  4. #4
    Join Date
    Apr 2011
    Posts
    124
    Thanks
    1
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows Symbian S60

    Default Re: QCoreApplication + event looping

    Most (but not all) signals will work, and a few (but not most) events will work without an event loop. But for general purposes you need one. (Though note that some system calls you make may contain calls to processEvents() within them.)

    QProcess isn't doing anything -- it's just the container for your executing code, and it's "command" is your program. You execute QCoreApplication.exec() when you see fit, to enable UI interaction. For a program with no UI interaction (and no other signal/event processing) there's no need for the exec() call at all.

    Understand that exec() basically is just:
    Qt Code:
    1. while (!quit) {
    2. processEvents();
    3. }
    To copy to clipboard, switch view to plain text mode 
    with logic to wait (vs burn CPU cycles) if no events are posted.

  5. #5
    Join Date
    Feb 2006
    Posts
    91
    Thanks
    4
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QCoreApplication + event looping

    Is there a way to find out what kind of signals/event work and which don't work ? Here I'm talking about the finished signal sent by QProcess which is working.
    Humans make mistake because there is really NO patch for HUMAN STUPIDITY

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

    Default Re: QCoreApplication + event looping

    The general rule is that signals that are emitted as a result of some lengthy process will not work and signals that are emitted as a direct result of a computation that takes place immediately will work.

    And for completeness, you can do this:
    Qt Code:
    1. class MyClass : public QObject {
    2. Q_OBJECT
    3. public:
    4. // ...
    5. public slots:
    6. void ProcessSomething(){...}
    7. };
    8.  
    9. int main(int argc,char** argv)
    10. {
    11. QCoreApplication app(argc, argv);
    12. MyClass obj;
    13. QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()),Qt::QueuedConnection);
    14. QTimer::singleShot(0, &obj, SLOT(ProcessSomething()));
    15. return app.exec();
    16. }
    To copy to clipboard, switch view to plain text mode 
    This will make your "ProcessSomething" method execute after app.exec() is called, when the event loop is already running.
    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
    Feb 2006
    Posts
    91
    Thanks
    4
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QCoreApplication + event looping

    Thanks, so by using
    QTimer::singleShot(0, &obj, SLOT(ProcessSomething()));
    we can be sure that the events are handled properly. I did use this method earlier but was not sure whether it was any different form just calling ProcessSomething() as both was working fine. But there could be cases where only QTimer::singleShot would work. One question though, isn't the 0 suppose to mean that the slot is to be executed immediately, or does it have a special meaning ? I didn't find anything on this in the manual.
    Humans make mistake because there is really NO patch for HUMAN STUPIDITY

  8. #8
    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: QCoreApplication + event looping

    One question though, isn't the 0 suppose to mean that the slot is to be executed immediately, or does it have a special meaning ? I didn't find anything on this in the manual.
    "0" does mean to execute immediately, but Qt executes it as soon as possible, that is it has to enter the event loop, only then Qt can respect (execute) the QTimer events, as you might have alrady figured out the event loop only starts inside exec()

    Just as a reference QTimer documentation says
    As a special case, a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed.
    Last edited by Santosh Reddy; 28th May 2011 at 10:26.

  9. #9
    Join Date
    Apr 2011
    Posts
    124
    Thanks
    1
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows Symbian S60

    Default Re: QCoreApplication + event looping

    The writeup on signals and slots in the Qt documentation will give some of the details about when signals are processed, but in general you can't count on them being immediate calls and you can't count on them not being immediate calls.

    Normally when you do a connect() with no connection type parm, signals within your code will be immediate if within a single thread. But many signals from the UI are effectively from a different thread and will be queued.

    Quote Originally Posted by wysota View Post
    The general rule is that signals that are emitted as a result of some lengthy process will not work and signals that are emitted as a direct result of a computation that takes place immediately will work.

    And for completeness, you can do this:
    Qt Code:
    1. class MyClass : public QObject {
    2. Q_OBJECT
    3. public:
    4. // ...
    5. public slots:
    6. void ProcessSomething(){...}
    7. };
    8.  
    9. int main(int argc,char** argv)
    10. {
    11. QCoreApplication app(argc, argv);
    12. MyClass obj;
    13. QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()),Qt::QueuedConnection);
    14. QTimer::singleShot(0, &obj, SLOT(ProcessSomething()));
    15. return app.exec();
    16. }
    To copy to clipboard, switch view to plain text mode 
    This will make your "ProcessSomething" method execute after app.exec() is called, when the event loop is already running.
    But then "ProcessSomething" will lock out event processing while it runs, and it's still apt to encounter problems if its own logic depends on the event loop running.

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

    Default Re: QCoreApplication + event looping

    Quote Originally Posted by DanH View Post
    Normally when you do a connect() with no connection type parm, signals within your code will be immediate if within a single thread. But many signals from the UI are effectively from a different thread and will be queued.
    This is not accurate. Signals are never queued and are always emitted immediately when a particular "emit x()" line is executed. Only slots can be queued.
    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.


  11. #11
    Join Date
    Apr 2011
    Posts
    124
    Thanks
    1
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows Symbian S60

    Default Re: QCoreApplication + event looping

    Whether a signal is queued or not is a function of the type of connect() used and whether the sender and receiver are in the same thread or different threads. No attribute of slot controls this.

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

    Default Re: QCoreApplication + event looping

    Quote Originally Posted by DanH View Post
    Whether a signal is queued or not is a function of the type of connect() used and whether the sender and receiver are in the same thread or different threads.
    Ok, so I have one signal connected to two slots, one slot is in the same thread as the object emitting the signal and the other slot is in a different thread. I now call "emit x()". When will the signal be emitted?

    No attribute of slot controls this.
    No attribute of signal controls this. It is an attribute of the connection which is responsible for triggering the slot. If you answer my question above, you'll understand it is the slot that is executed later, not the signal.
    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. #13
    Join Date
    Apr 2011
    Posts
    124
    Thanks
    1
    Thanked 10 Times in 10 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows Symbian S60

    Default Re: QCoreApplication + event looping

    Quote Originally Posted by wysota View Post
    Ok, so I have one signal connected to two slots, one slot is in the same thread as the object emitting the signal and the other slot is in a different thread. I now call "emit x()". When will the signal be emitted?
    Likely the signial in the same thread will be executed immediately, while the one in the different thread will be queued. But it could be that they both end up being queued.
    No attribute of signal controls this. It is an attribute of the connection which is responsible for triggering the slot. If you answer my question above, you'll understand it is the slot that is executed later, not the signal.
    There is a terminology problem here. There are four entities to consider: The emit, the slot, the connection, and the "signal", which is essentially a message. It is the delivery of this message to a slot which constitutes "executing" the signal. If something is queued, it is the signal.
    Qt::AutoConnection 0 (default) If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as Qt::QueuedConnection. Otherwise, the slot is invoked directly, behaving as Qt:irectConnection. The type of connection is determined when the signal is emitted.

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

    Default Re: QCoreApplication + event looping

    Quote Originally Posted by DanH View Post
    Likely the signial in the same thread will be executed immediately, while the one in the different thread will be queued. But it could be that they both end up being queued.
    Don't guess. If you don't know, rely on what someone else is saying or check in the source code. The signal (the method declared in the "signals" section) is executed only once. There can be zero or more slots connected to the signal and each of them will be executed when the right time comes. What you say wouldn't make sense if you had a signal connected to two slots living in different threads. How would the signal be emitted then? Would it be stalled until both threads were in their event loops at the same time? What if one of the threads wasn't running a loop at all?

    There is a terminology problem here.
    It is not, if you write what you have written above. And if a question is asked about which signals are deferred and which are emitted immediately. The question was about delays related to timers and networking operations (and other asynchronous operations) and not about slot execution and regardless of what lives in which thread. Networking signals (apart those signalling errors) will always be deferred despite the fact the internal connections are made within the same thread. The same goes with QtConcurrent signals, for instance.

    There are four entities to consider: The emit, the slot, the connection, and the "signal", which is essentially a message. It is the delivery of this message to a slot which constitutes "executing" the signal.
    No. You can invoke the slot without even having the signal by calling QMetaObject::invokeMethod() and it accepts an argument telling how the slot should be invoked (as a direct or queued connection albeit there is no connection there at all) and processing is exactly the same as with a signal, you also end up with the same QMetaObject::metacall() call.

    If something is queued, it is the signal.
    You are guessing again. And missing. The signal is emitted and when the slot is in another thread, it is transformed into an event and put in the event loop of the destination thread. When the thread processes its events, the data will be marshalled based on the event and the slot will be called. Look at the source code generated by the moc for a signal, it looks essentially like this:
    Qt Code:
    1. // SIGNAL 0
    2. void CMSMessageListener::messageReceived(CMSMessage _t1)
    3. {
    4. void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    5. QMetaObject::activate(this, &staticMetaObject, 0, _a);
    6. }
    To copy to clipboard, switch view to plain text mode 

    There is no check for threads here, the signal is activated immediately. Then activate() loops through the list of connections and either queues the metacall event or executes the slot immediately.
    Qt Code:
    1. void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
    2. void **argv){
    3. // ...
    4. do {
    5. QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
    6. // ...
    7. do {
    8. // ...
    9. QObject * const receiver = c->receiver;
    10. // ...
    11. if ((c->connectionType == Qt::AutoConnection
    12. && (currentThreadData != sender->d_func()->threadData
    13. || receiver->d_func()->threadData != sender->d_func()->threadData))
    14. || (c->connectionType == Qt::QueuedConnection)) {
    15. queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
    16. continue;
    17. } else if (c->connectionType == Qt::BlockingQueuedConnection) {
    18. blocking_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
    19. continue;
    20. }
    21. const int method = c->method;
    22. // ...
    23. metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
    24. } while (...);
    25. // ...
    26. } while (...);
    To copy to clipboard, switch view to plain text mode 

    If something is queued, it is the signal.
    To be precise it is a QMetaCallEvent that is queued. And considering the fact that if you have two connections to the same ("alien") thread you'll be getting two such events then I'd lean towards saying that it is the slot invokation that is being queued (especially that the event carries the slot id).
    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.


Similar Threads

  1. Replies: 2
    Last Post: 28th February 2011, 18:15
  2. Counting and looping properties
    By stefan in forum Qt Programming
    Replies: 2
    Last Post: 25th January 2011, 13:38
  3. Qmessagebox cant stop looping
    By Devoraz in forum Newbie
    Replies: 9
    Last Post: 7th August 2009, 07:34
  4. Use of QCoreApplication
    By moowy in forum Qt Programming
    Replies: 8
    Last Post: 18th May 2007, 08:33
  5. QtKey looping
    By VireX in forum Newbie
    Replies: 4
    Last Post: 15th February 2007, 20:52

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.