Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Sending Signals to Non-Qt-Thread - How?
QtWS25 Last Chance

Sending Signals to Non-Qt-Thread - How?

Scheduled Pinned Locked Moved General and Desktop
10 Posts 5 Posters 7.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    ansiwen
    wrote on last edited by
    #1

    Hi Qties,

    I have a simple goal: For thread-safe IPC I want to be able to send signals from a Qt-Gui-thread to a non-Qt-thread (read: does not use the Qt event loop). The solution is a lot more complicated than I thought, and I start to fear that it's not possible at all.

    I am experimenting with an alternative Qt/QML based GUI for our existing application (I will call it "backend" in this case). Therefore I wrote a simple QApplication that starts the backend in another QThread and an interface class that lives in both worlds/threads. The other direction, sending signals from the backend to the Qt thread was easy and works like a charm. But sending signals from Qt to the backend is harder than I thought.

    I don't want to regularly poll the event queue with hasPendingEvents() since it either induces delay or a performance burden. What I have so far is a local pipe to wake up the poll of the backend event loop in order to call processEvents() of the event dispatcher of the backend QThread. So the problem is now to trigger the wake-up whenever a signal is sent to the backend thread or, more precisely, whenever a postEvent() is done for a QObject belonging to the backend thread. Unfortunately I did not manage to achieve this yet. All options that come to my mind seem to have a dead-end. Here are my options so far:

    Replacing the eventloop of the backend with a Qt eventloop is not really an option, since we have our own pollset and timer mechanism, that is used all over the code. Since it's quite low level it's not easy to write a wrapper for it, and still the code has to remain compilable as a non-Qt-version.

    QAbstractEventDispatcher seems to be perfect to write a simple event dispatcher only for Qt events, which just triggers the pipe in the wakeUp() routine. The question is: While it's easy to install your own event dispatcher in the GUI thread, how do you install it in another QThread? I ended up reading the Qt sources and found the line: "// ### TODO: allow the user to create a custom event dispatcher" in corelib/thread/qthread_unix.cpp. Bummer!

    I found qt_register_signal_spy_callbacks() in corelib/kernel/qcoreapplication.cpp, with which I might capture the cases when a signal is emitted from the GUI to the backend. But this really doesn't look like an official way to solve problems, and I would have a burden on all signals that are emitted, not only that connected by Qt::QueuedConnection.

    I checked if from emitting the signal until the insertion into the event queue there are any other signals emitted that I could connect to, but I didn't find any. Also I don't see a possibility to install such signals, like in the generated meta object code, or by defining a notify callback for the event queue, like you can do on properties.

    I could just manually or by macro call the wake-up whenever I emit a signal of which I know it is connected to the backend thread. This is ugly, and I would only do it as a last resort.

    Of course the QAbstractEventDispatcher is the cleanest solution, but I want to stick with a standard Qt without custom patches and this is probably not on a short-term agenda of the Qt developers. So I ask you guys, do you have any other idea or suggestion how to solve this problem? Any hint is highly appreciated!

    Thanks in advance and best regards,

    Sven

    1 Reply Last reply
    0
    • G Offline
      G Offline
      giesbert
      wrote on last edited by
      #2

      Hi ansiwen,

      if you want to use signal/slot connection between threads, you must have an event queue (q Qt event queue) or do all the stuff on your own. AFAIK there is no other solution for that.

      Nokia Certified Qt Specialist.
      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

      1 Reply Last reply
      0
      • D Offline
        D Offline
        dangelog
        wrote on last edited by
        #3

        I'd go with 6: patch Qt and install your own QAbstractEventDispatcher for your thread :)

        Software Engineer
        KDAB (UK) Ltd., a KDAB Group company

        1 Reply Last reply
        0
        • A Offline
          A Offline
          ansiwen
          wrote on last edited by
          #4

          [quote author="peppe" date="1311801325"]I'd go with 6: patch Qt and install your own QAbstractEventDispatcher for your thread :)[/quote]

          That's basically 2. As I wrote, I also think, this is the cleanest solution, but I don't want to use a patched version for Qt. So, if I'd do that, I would do it in a way that it has good chances to get merged into the official Qt branch. There are several ways, how I could implement this. Therefore I need to know first, what's the best way in the eyes of the Qt devs.

          So, to whom do I have to talk to? Preferably it's the person that also decides, if the patch is accepted or not.

          1 Reply Last reply
          0
          • L Offline
            L Offline
            lgeyer
            wrote on last edited by
            #5

            #qt @ freenode or the "official mailing list":http://lists.qt.nokia.com.

            1 Reply Last reply
            0
            • A Offline
              A Offline
              ansiwen
              wrote on last edited by
              #6

              Just in case somebody ends up here with a similar problem: I implemented a new API to install event dispatcher in threads and submitted it half a year ago. It will be part of Qt 5. Here's the changeset (which also can be applied to Qt 4.8): https://codereview.qt-project.org/#change,8628

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                Interesting. I think your patch doesn't quite work as advertised though. It states that you can set a different event dispatcher as long as the thread has not started yet, but in fact you can set a dispatcher as long as no dispatcher has been set yet. So, this hypothetical example would not work:
                @
                QThread thread = new QThread(this);
                QAbstractEventDispatcher* d1 = new MyCustomEventDispatcher();
                thread->setEventDispatcher(d1); //no problems here...
                //...
                QAbstractEventDispatcher* d2 = new MyEvenMoreCustomEventDispatcher();
                thread->setEventDispatcher(d2); //fails! This is not expected IMHO

                thread->start();
                QAbstractEventDispatcher* d3 = new MyEvenMoreCustomEventDispatcher();
                thread->setEventDispatcher(d3); //fails too, as expected
                @

                Perhaps I misunderstood, but can you explain why installing d2 needs to fail? I'd say that as long as the thread is not started yet, there is no reason to disallow changing your mind on what dispatcher should be installed.

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  ansiwen
                  wrote on last edited by
                  #8

                  [quote author="Andre" date="1335515650"]Interesting. I think your patch doesn't quite work as advertised though. It states that you can set a different event dispatcher as long as the thread has not started yet, but in fact you can set a dispatcher as long as no dispatcher has been set yet.
                  [/quote]

                  The commit message is a bit misleading, but the documentation says "This is only possible as long as there is no event dispatcher installed for the thread yet." So this is a "set-once" operation.

                  [quote]
                  Perhaps I misunderstood, but can you explain why installing d2 needs to fail? I'd say that as long as the thread is not started yet, there is no reason to disallow changing your mind on what dispatcher should be installed.
                  [/quote]

                  The reason is KISS. It is very simple just to check, if there is an event dispatcher present. To re-set it, you would have to check, if the thread is running already and cleanly remove the old one. Also, I adapted the previous behavior: You couldn't instantiate two event dispatcher in Qt4, the second instantiation would fail for the same reason.

                  This is a rarely used feature, and the need to re-set the event dispatcher is even more rare, if existing at all. So, as long as there is no really good use case, I wouldn't take the effort and risk of implementing re-setting of the event dispatcher.

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andre
                    wrote on last edited by
                    #9

                    Thanks for your explanation. I don't quite see how checking the runstate would be more difficult than checking if a dispatcher has already been set. Isn't that as simple as this?

                    @
                    if (isStarted()) {
                    ...
                    }
                    @

                    The problem is, IMHO, is that it violates the property-based API that is recommended for Qt classes. I, at least, don't expect setters to act this way, and AFAIK, this behavior doesn't exist elsewhere in Qt.

                    On the other hand: I get that setting the property multiple times is highly unlikely, as setting it once is already something you do hardly ever.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      ansiwen
                      wrote on last edited by
                      #10

                      Well, you have to see that - although I wrote that patch - I'm quite a Qt newbie. So for me it is more trouble, since I have to read more code to make sure I do it right. Also none of my "Qt dev mentors" asked for this. So it is like it is, since it meets my needs, but as you know, you are invited to further improve it. ;-) (Although I wouldn't really see this as a Qt property)

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved