Results 1 to 17 of 17

Thread: QThread communication without signal and slots

  1. #1
    Join Date
    Oct 2006
    Posts
    83
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default QThread communication without signal and slots

    I have a worker thread that reimplements QThread's run() function. Within run() I need to update elements on the GUI. However, every tip I see so far is to use Signals/Slots to let the GUI know to update the screen. I don't want to do this because it sounds like using signals/slots would throw my desired update into a queue where it would sit until the main event loop rolled around. I'm simulating live video, so I need the worker thread to be able to call a function directly, from the main GUI thread.

    However, when I do it the way I want, my program crashes when the user starts moving the mouse around. Do you have any pointers on how to accomplish my goal?

    Some snippits of my current code:
    Qt Code:
    1. void VideoStreamEngine::run()
    2. {
    3. Image *img = NULL
    4. while (true)
    5. {
    6. server->GetFrame(&img);
    7. pParent->SetImage(img); // This is the GUI function that I want to call instead of using signals/slots
    8. }
    9. }
    10.  
    11.  
    12. void VideoRenderer::SetImage(Image *img)
    13. {
    14. mutex.lock();
    15. if (img != NULL)
    16. {
    17. image = // Some code to scale image into a 32-bit QImage
    18.  
    19. // Set QPixmap
    20. screenLabel->setPixmap( QPixmap::fromImage(*image) );
    21. }
    22. mutex.unlock();
    23. }
    To copy to clipboard, switch view to plain text mode 

    A Note: while digging through the docs...is "Qt:irectConnection" what I am looking for?
    Last edited by forrestfsu; 21st May 2007 at 19:14.

  2. #2
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread communication without signal and slots

    Calling the GUI thread function like that is equivalent of not using a worker thread at all.

    I have thought of one solution( other video apps seem to do it ): frame buffering ( actually a queue - something from the producer/consumer chapter ).
    The frame buffer should be shared between the GUI and worker threads and the access to it should be synchronized with a mutex.

    Amyway, the GUI thread should read data while it is available( if not, it should wait ), and take what it reads from the buffer. On the other side, the worker thread pushes frames in the buffer.

    You should set a reasonable buffer size ( probably based on frame resolution - minimum 2-4 mb ).

    Sending frame by frame will take you nowhere. But that is just my opinion.
    Maybe the guys have a better idea.

    Regards

  3. #3
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread communication without signal and slots

    Anyway, there is no need to use a mutex there because no one else is accessing that data.
    There is no one else to protect it from.
    The worker thread generates one frame and the GUI comes and draws it. And that is it.

    Regards

  4. #4
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread communication without signal and slots

    A Note: while digging through the docs...is "QtirectConnection" what I am looking for?
    No .
    Direct connection is exactly what you need to avoid! And anyway, this is kinda what you're using now. Connecting to the GUI thread through direct connection means that you're executing the GUI thread slot in the context of the worker thread - which again is not good because you're modifying a widget inside.

    Try thinking of what I proposed to you. BTW - you have to implement that using queued connections.

    Regards

  5. #5
    Join Date
    Oct 2006
    Posts
    83
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Thanks for the pointers Marcel. Let me attempt to clarify what the Thread is actually doing. There is a whole lot more going on then the snippit I put up. The point of the thread was because the "server->GetFrame(&img);" call hangs until a new frame is available. Because of this, I wanted it to be in it's own thread. As far as creating a buffer, yes we have done this and it's intended for video playback. However, we have a "Live Video" mode which is what I'm currently talking about. The "GetFrame" function will return the latest available image. So the point is not to keep any sort of buffer, but just to display the last available frame as fast as possible. It's weird, with the code I displayed earlier: it will display the video perfectly fine until I start moving the mouse around...and then the terminal throws out a bunch of error messages like "X Error: BadRequest..."

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: QThread communication without signal and slots

    You can't do it like this and using a mutex won't help. You might be calling setPixmap() the same moment when the other thread calls pixmap(). You have to set the image from the other thread. You can use custom events to deliver the pointer or store it in some synchronized variable and signal the main thread to pick it up.

  7. #7
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread communication without signal and slots

    o the point is not to keep any sort of buffer, but just to display the last available frame as fast as possible. It's weird, with the code I displayed earlier: it will display the video perfectly fine until I start moving the mouse around...and then the terminal throws out a bunch of error messages like "X Error: BadRequest..."
    That is because you're modifying a widget from another thread.
    I told you that function will be executed in the context of the worker thread. And widgets can be modified only by the GUI thread.
    Try passing it through a signal to the GUI thread, or some custom event, because this is not the way to go.

  8. #8
    Join Date
    Oct 2006
    Posts
    83
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Thanks guys, I think I'm following what you are saying. I just wanted to make sure that you both realized that the two functions I wrote are in two separate classes, one in the worker thread and one in the GUI thread. So, I was not really doing any paint calls in the worker thread. Are you saying that I shouldn't be calling SetImage, because SetImage's function belongs to a QWidget which is part of the main GUI thread? In that case, yes I can use Signal's and Slots to let the GUI thread become aware that it needs to do work. However, I was trying to stay away from Signal's and Slot's because I wanted to directly call the function instead of putting it in a queue.

    Qt Code:
    1. // VideoStreamEngine is on "Worker Thread"
    2. void VideoStreamEngine::run()
    3. {
    4. Image *img = NULL
    5. while (true)
    6. {
    7. server->GetFrame(&img); // hangs until a frame is available
    8. pParent->SetImage(img); // This is the GUI function that I want to call instead of using signals/slots
    9. }
    10. }
    11. // -----------------------------------------------------
    12. // VideoRenderer class is on "GUI Thread"
    13. void VideoRenderer::SetImage(Image *img)
    14. {
    15. if (img != NULL)
    16. {
    17. image = ... // Some code to scale img into a 32-bit QImage
    18.  
    19. // Set QPixmap
    20. screenLabel->setPixmap( QPixmap::fromImage(*image) );
    21. }
    22. }
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: QThread communication without signal and slots

    You can't call it directly because the other thread can be in an unpredictable state at that time. The point of queuing the request is to synchronise both threads.

  10. #10
    Join Date
    Feb 2006
    Location
    Romania
    Posts
    2,744
    Thanks
    8
    Thanked 541 Times in 521 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread communication without signal and slots

    I just wanted to make sure that you both realized that the two functions I wrote are in two separate classes, one in the worker thread and one in the GUI thread.
    Well, yes we did .
    They are in two separate threads, but the way you call them is wrong. You might as well call screenLabel->setPixmap from the worker thread. You would get the same result.

    So, I was not really doing any paint calls in the worker thread
    Not explicitly, but setting the pixmap will trigger a paint event.
    QWidgets are not reentrant, nor thread safe. That means you cannot access/modify them from two threads.
    While you access them in one thread, the widgets may process and event in the GUI thread and possibly change their member data, compromising your other thread.

    However, I was trying to stay away from Signal's and Slot's because I wanted to directly call the function instead of putting it in a queue.
    You shouldn't notice any delay or lags if you do things right.

    I think I'm following what you are saying
    Then why didn't you modified your code?

  11. #11
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Calling a function 'in another thread' is impossible by definition. Threads can split, merge and even synchronize, but they're like distinct processes that happen to share the same memory.

    The only way to communicate is to set data somewhere where you know the other thread is going to find it. That is what signals and slots do.

    Threads work this way for a reason. You wouldn't want to interrupt the other thread in the middle of a computation, would you?
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: QThread communication without signal and slots

    Quote Originally Posted by marcel View Post
    Not explicitly, but setting the pixmap will trigger a paint event.
    You don't have to paint and paint event is not a danger here at all, because it'll be scheduled for the right thread. The problem is that you modify the object data while something else might be accessing it.

    Quote Originally Posted by Michiel View Post
    Calling a function 'in another thread' is impossible by definition. Threads can split, merge and even synchronize, but they're like distinct processes that happen to share the same memory.

    The only way to communicate is to set data somewhere where you know the other thread is going to find it. That is what signals and slots do.
    They share code and data and in theory in some cases you could probably access the stack and change the return address of the current frame

  13. #13
    Join Date
    Oct 2006
    Posts
    83
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Thanks to the both of you. I went ahead and used signals and slots and I don't see any delay in the video so far.

  14. #14
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Quote Originally Posted by wysota View Post
    They share code and data and in theory in some cases you could probably access the stack and change the return address of the current frame
    Yeah. You could also access the private member variables of a strange class by using pointer arithmetic.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  15. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: QThread communication without signal and slots

    Quote Originally Posted by Michiel View Post
    Yeah. You could also access the private member variables of a strange class by using pointer arithmetic.
    There are easier ways to do that. Even Qt does that, by the way

  16. #16
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: QThread communication without signal and slots

    Really? Well, I wouldn't know. I only write nice code.

    Qt just went down a notch in my book. Private member vars are private for a reason.

    There. My joke reply started a serious discussion.
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  17. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    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: QThread communication without signal and slots

    Quote Originally Posted by Michiel View Post
    Private member vars are private for a reason.
    And they violate that rule for a reason as well. So far I have only seen one occurence of it in Qt code. Maybe there are more or maybe there aren't any now that Qt 4.3 arrives.

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.