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.7k 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.
  • Christian EhrlicherC Offline
    Christian EhrlicherC Offline
    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 Offline
          Christian EhrlicherC Offline
          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