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. Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads
Qt 6.11 is out! See what's new in the release blog

Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 4 Posters 7.6k Views 1 Watching
  • 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.
  • S Offline
    S Offline
    Superlokkus
    wrote on last edited by
    #1

    It seems to me QMetaObject::invokeMethod with Qt::QueuedConnectionis a common seen pattern to invoke slots from non qt managed, especially non main threads. However QMetaObject::invokeMethod is not documented as thread safe, as far as I can tell, but it's behaviour suggests it.

    Is it thread safe or not?
    If not what would be a good alternative to invoke slots on QMetaObjects from non qt managed threads? Background ( https://stackoverflow.com/q/53803018/3537677 )

    1 Reply Last reply
    0
    • Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      It's not documented as thread-safe because it can't be guaranteed. e.g. when the receiver is deleted during the invokeMethod() call you'll get in trouble. When you don't modify the receiver (which is likely the case in your usecase) it's thread-safe afaics.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      S 1 Reply Last reply
      2
      • Christian EhrlicherC Christian Ehrlicher

        It's not documented as thread-safe because it can't be guaranteed. e.g. when the receiver is deleted during the invokeMethod() call you'll get in trouble. When you don't modify the receiver (which is likely the case in your usecase) it's thread-safe afaics.

        S Offline
        S Offline
        Superlokkus
        wrote on last edited by
        #3

        @Christian-Ehrlicher said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

        when the receiver is deleted

        I would not define this as thread-safe, it would be thread safe, if the internals of QMetaObject::invokeMethod is reentrant, and given the caller makes sure about the life times, i.e. documented constraint on it's parameters. First statement includes the thread safe handling of Qt globals.

        it's thread-safe afaics

        Exactly that "AFAIK" is what my question here is about. Because either it's true, then it should be documented, or not, which would mean many solutions are wrong, and the questions remains, what could be used.

        1 Reply Last reply
        0
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Since I don't know the exact internals the only way I see is to create a bug report report and ask directly.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          S 1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            Since I don't know the exact internals the only way I see is to create a bug report report and ask directly.

            S Offline
            S Offline
            Superlokkus
            wrote on last edited by Superlokkus
            #5

            @Christian-Ehrlicher said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

            Since I don't know the exact internals the only way I see is to create a bug report report and ask directly.

            Just opened
            https://bugreports.qt.io/browse/QTBUG-72599

            kshegunovK 1 Reply Last reply
            0
            • dheerendraD Offline
              dheerendraD Offline
              dheerendra
              Moderators Qt Champions 2024 Qt Champions 2022 Qt Champions 2017
              wrote on last edited by
              #6

              I don't think this will be thread safe. This will get instance of metaobject and is single instance for all the subclasses of qobject. QObject itself is not thread safe. Invoke method access many internal pointers which are not protected. It also accesses qobject pointer

              Dheerendra
              @Community Service
              Certified Qt Specialist
              https://www.pthinks.com

              1 Reply Last reply
              0
              • Christian EhrlicherC Online
                Christian EhrlicherC Online
                Christian Ehrlicher
                Lifetime Qt Champion
                wrote on last edited by
                #7

                The specific problem was about a queued connection which is more or less a QCoreApplication::postEvent() which is thread safe ...

                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                Visit the Qt Academy at https://academy.qt.io/catalog

                1 Reply Last reply
                2
                • S Superlokkus

                  @Christian-Ehrlicher said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                  Since I don't know the exact internals the only way I see is to create a bug report report and ask directly.

                  Just opened
                  https://bugreports.qt.io/browse/QTBUG-72599

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by
                  #8

                  invokeMethod is thread-safe with the Qt::QueuedConnection argument in the sense that it's going to do what you expect it to - i.e. put a message in the receiving thread's event loop for a meta-call. It is most certainly not thread-safe when used with Qt::AutoConnection.

                  I would not define this as thread-safe, it would be thread safe, if the internals of QMetaObject::invokeMethod is reentrant

                  Thread-safety and reentrancy are orthogonal to each other. A function can be thread-safe and non-reentrant (which invokeMethod actually is with the Qt::QueuedConnection, as it operates on the threading globals) or vice versa ... or any combination thereof.

                  Read and abide by the Qt Code of Conduct

                  S 1 Reply Last reply
                  3
                  • dheerendraD Offline
                    dheerendraD Offline
                    dheerendra
                    Moderators Qt Champions 2024 Qt Champions 2022 Qt Champions 2017
                    wrote on last edited by
                    #9

                    If it is queues connection as @kshegunov said it will just place in destination thread and move on. If multiple threads call same method with queued connection I don't see issue. If it mixes connection type then it shud create issue.

                    Dheerendra
                    @Community Service
                    Certified Qt Specialist
                    https://www.pthinks.com

                    1 Reply Last reply
                    0
                    • kshegunovK kshegunov

                      invokeMethod is thread-safe with the Qt::QueuedConnection argument in the sense that it's going to do what you expect it to - i.e. put a message in the receiving thread's event loop for a meta-call. It is most certainly not thread-safe when used with Qt::AutoConnection.

                      I would not define this as thread-safe, it would be thread safe, if the internals of QMetaObject::invokeMethod is reentrant

                      Thread-safety and reentrancy are orthogonal to each other. A function can be thread-safe and non-reentrant (which invokeMethod actually is with the Qt::QueuedConnection, as it operates on the threading globals) or vice versa ... or any combination thereof.

                      S Offline
                      S Offline
                      Superlokkus
                      wrote on last edited by
                      #10

                      @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                      Thread-safety and reentrancy are orthogonal to each other.
                      I know, however since we don't have to deal with Interrupts here, in practice reentrancy usually is a precondition for thread safety, because, when a function can not be called in thread A, while it has been execute to some in between state in Thread B, what is thread safety then.

                      But anyway, that constraints, like "QMetaObject::invokeMethod is thread safe when called with Qt::QueuedConnection and with recipient and parameters living at least until slot completion or something" should be documented, so one can be sure, that it really is. (However for the parameters should be fine with Q_ARGS, call by value AFAIK)

                      kshegunovK 1 Reply Last reply
                      0
                      • S Superlokkus

                        @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                        Thread-safety and reentrancy are orthogonal to each other.
                        I know, however since we don't have to deal with Interrupts here, in practice reentrancy usually is a precondition for thread safety, because, when a function can not be called in thread A, while it has been execute to some in between state in Thread B, what is thread safety then.

                        But anyway, that constraints, like "QMetaObject::invokeMethod is thread safe when called with Qt::QueuedConnection and with recipient and parameters living at least until slot completion or something" should be documented, so one can be sure, that it really is. (However for the parameters should be fine with Q_ARGS, call by value AFAIK)

                        kshegunovK Offline
                        kshegunovK Offline
                        kshegunov
                        Moderators
                        wrote on last edited by kshegunov
                        #11

                        I think you misunderstand. QMetaObject::invokeMethod does not execute the method when it's called with Qt::QueuedConnection, which is the whole point of it. Instead it creates a QEvent::MetaCall event and puts it into the receiving object's thread's event queue. This all means that the event is processed (as all posted events) synchronously from the receiving thread's event loop. So you kind of lose the idea of "thread-safe" as you're not really calling the method itself. The receiving thread will call it when it gets to it. Unless if you mean if the actual event posting is thread-safe, then the answer is "yes, most certainly".

                        Read and abide by the Qt Code of Conduct

                        S 1 Reply Last reply
                        2
                        • kshegunovK kshegunov

                          I think you misunderstand. QMetaObject::invokeMethod does not execute the method when it's called with Qt::QueuedConnection, which is the whole point of it. Instead it creates a QEvent::MetaCall event and puts it into the receiving object's thread's event queue. This all means that the event is processed (as all posted events) synchronously from the receiving thread's event loop. So you kind of lose the idea of "thread-safe" as you're not really calling the method itself. The receiving thread will call it when it gets to it. Unless if you mean if the actual event posting is thread-safe, then the answer is "yes, most certainly".

                          S Offline
                          S Offline
                          Superlokkus
                          wrote on last edited by
                          #12

                          @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                          Unless if you mean if the actual event posting is thread-safe, then the answer is "yes, most certainly".

                          Exactly that is what I meant! Thats the reason why I tried to use QCoreApplication::postEvent first, since it seemed to me as the only thread safe way, to post an event to the global qt event queue.

                          kshegunovK 1 Reply Last reply
                          0
                          • S Superlokkus

                            @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                            Unless if you mean if the actual event posting is thread-safe, then the answer is "yes, most certainly".

                            Exactly that is what I meant! Thats the reason why I tried to use QCoreApplication::postEvent first, since it seemed to me as the only thread safe way, to post an event to the global qt event queue.

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by
                            #13

                            Thats the reason why I tried to use QCoreApplication::postEvent first

                            It is one way. You can't create QEvent::MetaCall events for it, however, this is where QMetaObject::invokeMethod comes into play.

                            to post an event to the global qt event queue.

                            There's no global event queue, there's an event queue for each thread that starts one with QEventLoop::exec (which the main thread does through QCoreApplication::exec).

                            Read and abide by the Qt Code of Conduct

                            S 1 Reply Last reply
                            3
                            • kshegunovK kshegunov

                              Thats the reason why I tried to use QCoreApplication::postEvent first

                              It is one way. You can't create QEvent::MetaCall events for it, however, this is where QMetaObject::invokeMethod comes into play.

                              to post an event to the global qt event queue.

                              There's no global event queue, there's an event queue for each thread that starts one with QEventLoop::exec (which the main thread does through QCoreApplication::exec).

                              S Offline
                              S Offline
                              Superlokkus
                              wrote on last edited by Superlokkus
                              #14

                              @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                              There's no global event queue, there's an event queue for each thread that starts one with QEventLoop::exec (which the main thread does through QCoreApplication::exec).

                              Yeah sorry, I often forget that you can also create extra QThreads/Widgets with own event loops. With global I meant of course the stuff you get by QCoreApplication::instance, like you said, (which AFAIK is special as it needs to be pumped in order to Qt in general to work), but thanks for clarifying.

                              However I just posted my "solution" aka version of the common pattern: https://stackoverflow.com/a/53806409/3537677 with also some assumptions by me, which of course you are invited to review!

                              kshegunovK 1 Reply Last reply
                              0
                              • S Superlokkus

                                @kshegunov said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                                There's no global event queue, there's an event queue for each thread that starts one with QEventLoop::exec (which the main thread does through QCoreApplication::exec).

                                Yeah sorry, I often forget that you can also create extra QThreads/Widgets with own event loops. With global I meant of course the stuff you get by QCoreApplication::instance, like you said, (which AFAIK is special as it needs to be pumped in order to Qt in general to work), but thanks for clarifying.

                                However I just posted my "solution" aka version of the common pattern: https://stackoverflow.com/a/53806409/3537677 with also some assumptions by me, which of course you are invited to review!

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on last edited by kshegunov
                                #15

                                @Superlokkus said in Thread safety of QMetaObject::invokeMethod e.g. slot invoking from random threads:

                                which AFAIK is special as it needs to be pumped in order to Qt in general to work

                                No not really. QCoreApplication::exec just does QEventLoop::exec ... :)

                                PS:
                                Ah, I see Giuseppe already answered you. One note on your call, if you're using Qt 5.10+ you can use QMetaObject::invokeMethod with functors (i.e. lambdas or pointers to methods), which is often more convenient and less error prone than resolving the method address through its name.

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply
                                2

                                • Login

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