Results 1 to 14 of 14

Thread: Signals are delayed on X11?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Signals are delayed on X11?

    I observed the following behaviour when running an application with background threads on Linux:

    I start a thread with the press of a button. The thread emits hundreds of signals with a very fast pace (12 ms). The signals are connected to the slot of another thread, which is already running, but the signals do not arrive. Only when I click somewhere on the gui again, suddenly a signal havoc reaches the second thread. It seems to me that the signals from the first thread were delayed, until I did something with the gui, then suddenly all the signals were handled at once. This does not happen on Windows.

    Is there anything I can do to force the signals to be handled immidiately?

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

    Default Re: Signals are delayed on X11?

    You might try not to starve one thread by eating all the cpu time in the other one. Use a lower priority or do something else to make sure the main thread gets its slice of cpu sometimes.

  3. #3
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Signals are delayed on X11?

    Both threads are actually quite lightweight. The one does some short calculation with a 12 ms sleep and the other handles serial communication by sending and receiving a 60 byte packet with 20 ms sleep. But well, as for your usual advice, I will see if I can make an improvement with a timer based approach.

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

    Default Re: Signals are delayed on X11?

    Could you show us the thread object creation and connect statement code?

  5. #5
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Signals are delayed on X11?

    Certainly. The complete code of the two threads is attached. And here is some more explanation for easier understanding.

    My software is a motion editor for a humanoid robot. The robot is connected to the PC on a serial port. The idea is to move the robot's body with your hands and record the robot's poses (sets of joint angles) in the meantime. At a later time you can play back a sequence of poses and the robot will execute it and perform the same motion that you showed it with your hands. The robot is also virutally visualized with a 3D skeleton on the screen and lots of spin boxes are showing the current joint angle values.

    Attached you will find the classes of two threads. The RobotInterface is handling the serial communication. It's active the whole time, it constantly exchanges packets with the robot at a pace of approx. 20 ms. The KeyframePlayer is triggered by the press of a button on the gui. It takes the currently loaded motion sequence, samples it with a pace of 12 ms, generates joint angles and gives them to the RobotInterface to be sent to the robot.

    The connecting code I will show you right here:

    Qt Code:
    1. /*
    2.  * Starts playing the keyframes in the motion sequence.
    3.  * The keyframe player gets connected to the robot interface and to the keyframe editor.
    4.  * Attention! If the robot is actuated, it will execute the current motion.
    5.  */
    6. void MotionEditor::on_playButton_clicked()
    7. {
    8. // Abort if already running.
    9. if (keyframePlayer.running)
    10. {
    11. playerDone();
    12. }
    13.  
    14. else
    15. {
    16. //connect(&keyframePlayer, SIGNAL(jointAnglesChanged(QHash<QString, float>)),
    17. &robotInterface, SLOT(setTxJointAngles(QHash<QString, float>)));
    18.  
    19. // Start the player thread.
    20. keyframePlayer.playTheseFrames(motionSequence->getKeyframes());
    21. }
    22. }
    To copy to clipboard, switch view to plain text mode 

    Well it's a bit boring right now, because I commented the connect() call out. The reason is the problem I described. Since I found transfering the data by signals and slots to be unreliable for now, I changed the KeyframePlayer a bit and added direct calls to the RobotInterface. If you search for the keyword "setTxJointAngles" in KeyframePlayer, you will find all the relevant spots. The signals are still emitted though, it's only the connect() call above that I commented out for now.


    I will be happy if you actually take a look at it and provide some guru advice.

    While I already know I have it coming, yes, thread safety is actually an issue that I haven't addressed yet. What I did so far is I pass a jointAngles QHash by value from the KeyframePlayer to the RobotInterface. The RobotInterface reads it and sends it to the robot. In the meantime it's very likely, that the KeyframePlayer overwrites the very same QHash. I was hoping that implicit sharing will be good enough, but it's not the case. The software crashes many times at this point. I'm not sure yet how I can solve this problem in a nice way, so if you can throw me a penny, I will be very thankful.
    Attached Files Attached Files

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

    Default Re: Signals are delayed on X11?

    Ok, three things.

    1. I wouldn't transmit a QHash object across signals/slots between threads because at least one of two reasons - thread safety (two threads accessing a single object at the same time) or performance (serializing and deserializing the hash). Maybe you should have a single shared buffer (it can be a QHash object) protected with a mutex where you store values and signal the other thread they are ready.

    2. Your thread objects probably live in the main thread so all signals emitted by them and all slots they contain are executed in the context of the main thread and not your "worker" threads which is probably not what you want. You should use QObject::moveToThread() to push those objects to their respective threads.

    3. When you do what I said in the previous point, you will probably notice your slots are not executed at all. That's because a thread needs an event loop running to be able to execute slots across threads so you need to change your approach to an event driven one at least in the thread you want to process signals from other threads. It shouldn't be too hard in your case - just call exec() from run() and use timers with appropriate timeouts (like 12ms and 0 or more) to do your work.

  7. #7
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Signals are delayed on X11?

    I'm sorry, I don't really understand any of those things.

    1. I wouldn't transmit a QHash object across signals/slots between threads because at least one of two reasons - thread safety (two threads accessing a single object at the same time) or performance (serializing and deserializing the hash).
    The thread safety is clear. The serialization is not. The QHash is serialized when I pass it by value? Because here it says that due to implicit sharing it's actually just like passing only a pointer. And here it even explicitly says that it's safe to pass implicitly shared containers between threads (does not imply thread safety).

    2. Your thread objects probably live in the main thread so all signals emitted by them and all slots they contain are executed in the context of the main thread and not your "worker" threads which is probably not what you want. You should use QObject::moveToThread() to push those objects to their respective threads.
    Yes this is true, the QThread objects are created and started from the main thread. What does it mean that "all signals emitted by them and all slots they contain are executed in the context of the main thread"? Why is it not what I want?

    Point 3. I probably don't even need to think about until I understand point 2.


    In any case, I found the reason why my signals were behaving so strange. It's embarassing, but the truth is that there was a mistake in my code. Here is the culprit:

    Qt Code:
    1. while (jointIterator.hasNext())
    2. {
    3. jointIterator.next();
    4. jointAngles[jointIterator.key()] += steps[jointIterator.key()];
    5. emit jointAnglesChanged(jointAngles);
    6. }
    To copy to clipboard, switch view to plain text mode 

    The signal was sent out for every single joint instead of just once after all joint angles have been changed. 20 signals every 12 ms are a lot. Actually it should read:

    Qt Code:
    1. while (jointIterator.hasNext())
    2. {
    3. jointIterator.next();
    4. jointAngles[jointIterator.key()] += steps[jointIterator.key()];
    5. }
    6.  
    7. emit jointAnglesChanged(jointAngles);
    To copy to clipboard, switch view to plain text mode 

    So now that I fixed this everything works like expected on Windows and on Linux.

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

    Default Re: Signals are delayed on X11?

    Quote Originally Posted by Cruz View Post
    The thread safety is clear. The serialization is not. The QHash is serialized when I pass it by value?
    It is serialized when you use queued (across threads) signal-slot connections. The data has to be stored somewhere so that the other thred can use it when it decides to handle a signal event. This is to assure thread-safety and object consistency.

    Because here it says that due to implicit sharing it's actually just like passing only a pointer. And here it even explicitly says that it's safe to pass implicitly shared containers between threads (does not imply thread safety).
    Yes, that's all true but it doesn't say what happens if signal-slot mechanism across threads kicks in. Implicit sharing still helps but remember you may be trying to access (modify) the same object from different threads so it is safe to assume you receive a detached copy of the object in the slot which requires a deep copy. This isn't that expensive with QHash especially if it has 20 cells but if you do that 50 times per second, the overall cost can be significant.

    What does it mean that "all signals emitted by them and all slots they contain are executed in the context of the main thread"?
    Read about "thread affinity" and "queued connections" in Assistant.

    Why is it not what I want?
    Because it can break your application and it makes the use of threads somewhat questionable if you access the main thread from worker threads.

    Point 3. I probably don't even need to think about until I understand point 2.
    Just try it and see for yourself. You can also test it by blocking the event loop of the main thread - you will see the slots won't be executing at all.

    So now that I fixed this everything works like expected on Windows and on Linux
    But the questionable design of emitting signals on behalf of wrong threads remains. You might stumble upon this problem later on when your application becomes more complex and it will be much more expensive to solve it then, so it's better to handle it now.

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

    Cruz (17th February 2009)

  10. #9
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Signals are delayed on X11?

    Ok I understand thread affinity and thread event loops now.

    The two Qthreads are both created in the main thread. The internal objects the threads use are created in the thread where appropriate. So there is nothing I would need to move to a thread.

    The internal objects of the threads don't need any signal handling, so the threads don't need any event loops. The signals of the threads themselves should be queued by the main thread, so everything is ok about this.

    The only thing left is to take care of thread safety, when one thread passes a QHash to the other. I started a new topic about this, because this one was actually about delayed signals in X11.

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

    Default Re: Signals are delayed on X11?

    Quote Originally Posted by Cruz View Post
    The two Qthreads are both created in the main thread. The internal objects the threads use are created in the thread where appropriate. So there is nothing I would need to move to a thread.
    Do you emit signals on behalf of the "internal objects" or the thread object? If "RobotInterface" and "KeyframePlayer" inherit QThread then you are exactly in the situation I'm talking about.

    The internal objects of the threads don't need any signal handling, so the threads don't need any event loops. The signals of the threads themselves should be queued by the main thread, so everything is ok about this.
    I'm not sure you are right. It would be easier to talk about it if you provided header files for both your classes.

    The only thing left is to take care of thread safety, when one thread passes a QHash to the other.
    The only clash that may occur in current situation is when emitting the signal carrying the hash but only if you access the same instance of QHash at some other place in code. As long as you use local objects only and make sure they are detached from other instances before emitting them, you should be safe. Just know it's a bad design which can turn into obstacle later on.

  12. #11
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Signals are delayed on X11?

    I attached the header files.

    All the signals coming from those threads are targeted at the main thread. Except for one, which is the signal that carries the joint angles from the KeyframePlayer thread to the RobotInterface thread. So the point you are trying to make is that I should actually queue this one signal and handle it in the RobotInterface's event loop? I still don't understand why it's a bad thing if the main thread handles the signal. What exactly goes wrong?
    Attached Files Attached Files

Similar Threads

  1. Signals and Slots Problem
    By GenericProdigy in forum Qt Programming
    Replies: 4
    Last Post: 2nd February 2009, 09:06
  2. Signals and Slots
    By 83.manish in forum Qt Programming
    Replies: 3
    Last Post: 30th June 2008, 10:31
  3. Problem with SpinBox signals and slots
    By ramstormrage in forum Newbie
    Replies: 4
    Last Post: 2nd May 2008, 01:45
  4. QThread and signals (linux/UNIX signals not Qt Signals)
    By Micawber in forum Qt Programming
    Replies: 1
    Last Post: 28th November 2007, 22:18
  5. KDE Signals
    By chombium in forum KDE Forum
    Replies: 1
    Last Post: 25th January 2006, 18:45

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.