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.8k 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 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 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