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. Non-Reentrant Class Use In Multithreaded Program
Forum Updated to NodeBB v4.3 + New Features

Non-Reentrant Class Use In Multithreaded Program

Scheduled Pinned Locked Moved Solved General and Desktop
64 Posts 6 Posters 19.6k Views 4 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by kshegunov
    #52

    The thing is: what guarantees do you have that the OS doesn't spin a new thread to handle whatever operation you are asking it to do?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    1
    • C Offline
      C Offline
      Crag_Hack
      wrote on last edited by
      #53

      I'll share this stackoverflow post here (I am using a static callback worker thread object method instead of a global callback): I ran an experiment using CopyCallEx. I did a qDebug() << QThread::currentThreadId(); in the worker thread and in the CopyFileEx static callback function and they displayed the same thread. Also I put a qDebug() after the CopyFileEx call in the worker thread and the CopyFileEx call blocked synchronously until it finished. Does this mean I can call CopyFileEx directly from my worker thread object and access worker thread object member functions directly from the static callback function?

      1 Reply Last reply
      0
      • C Offline
        C Offline
        Crag_Hack
        wrote on last edited by Crag_Hack
        #54

        So with regard to your concern with the OS spinning a new thread for CopyFileEx, does my experiment show otherwise? Is it thus safe to access worker thread object methods directly from the progress callback function?
        Thanks

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #55

          From the looks of it, since it's a blocking call, it should be safe. However, I'd recommend that you put a comment in your code explaining this.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • C Offline
            C Offline
            Crag_Hack
            wrote on last edited by
            #56

            I'm implementing the callback now but am having a simple issue.

            DWORD Worker::copyProgress(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred, DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst, LPVOID data)
            {
                Worker *thisWorker = qobject_cast<Worker *>(data);
            

            compiler complains:

            C2665: 'qobject_cast': none of the 2 overloads could convert all the argument types
            
            could be 'T *qobject_cast<Worker*>(const QObject *)'
            
            or       'T *qobject_cast<Worker*>(QObject *)'
            
            while trying to match the argument list '(LPVOID)'
            

            What's up with this guy? Google didn't show much info...

            1 Reply Last reply
            0
            • C Offline
              C Offline
              Crag_Hack
              wrote on last edited by JKSH
              #57

              Found what I was looking for...
              https://stackoverflow.com/questions/39592202/converting-between-qobject-and-void

              1 Reply Last reply
              0
              • C Offline
                C Offline
                Crag_Hack
                wrote on last edited by Crag_Hack
                #58

                Another obstacle to overcome - the CopyFileEx function only accepts LPBOOL, which is
                typedef BOOL far *LPBOOL; and typedef int BOOL;,
                so I can't use my volatile std::atomic_bool cancel I was using before. What's the best way to solve this problem? Do I have to use a normal non-atomic LPBOOL to pass to the CopyFileEx function? If so do I need to use a mutex for the cancel bool that allows me to cancel the file copy logic when requested? If so where do I put the mutexes? Thanks. Here's the current code.

                class Worker : public QObject
                {
                public:
                    void stop() { cancel = true; }
                    volatile std::atomic_bool cancel;
                ...
                void Replicator::stopWork()
                {
                    if (isBusy)
                        worker->stop();
                }
                
                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #59

                  @Crag_Hack said in Non-Reentrant Class Use In Multithreaded Program:

                  CopyFileEx

                  It's not the same variable, don't mix stoping your Worker with Stoping CopyFileEx.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • C Offline
                    C Offline
                    Crag_Hack
                    wrote on last edited by Crag_Hack
                    #60

                    But I need to be able to stop the worker thread from the gui thread, not just when the program is scanning files but also when it is copying files, using the same cancel condition as created by clicking the cancel button in the gui thread. All the logic is handled in the worker thread both scanning, volume shadow copy service, file copying and everything. All of these operations need to be cancelled if desired. The worker thread remains alive it just gets reused for each backup that is performed. I did just find a workaround as per your suggestion got my creative juices flowing... I can check the std::atomic_bool cancel variable in the CopyFIleEx progress callback function and if it is true then return PROGRESS_CANCEL. Can you think of another way to do this though? Just curious.

                    kshegunovK 1 Reply Last reply
                    0
                    • C Crag_Hack

                      But I need to be able to stop the worker thread from the gui thread, not just when the program is scanning files but also when it is copying files, using the same cancel condition as created by clicking the cancel button in the gui thread. All the logic is handled in the worker thread both scanning, volume shadow copy service, file copying and everything. All of these operations need to be cancelled if desired. The worker thread remains alive it just gets reused for each backup that is performed. I did just find a workaround as per your suggestion got my creative juices flowing... I can check the std::atomic_bool cancel variable in the CopyFIleEx progress callback function and if it is true then return PROGRESS_CANCEL. Can you think of another way to do this though? Just curious.

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

                      @Crag_Hack said in Non-Reentrant Class Use In Multithreaded Program:

                      I can check the std::atomic_bool cancel variable in the CopyFIleEx progress callback function and if it is true then return PROGRESS_CANCEL. Can you think of another way to do this though?

                      This sounds like a decent plan to me.

                      Read and abide by the Qt Code of Conduct

                      1 Reply Last reply
                      0
                      • C Offline
                        C Offline
                        Crag_Hack
                        wrote on last edited by Crag_Hack
                        #62

                        Will this code maintain the atomicity of the cancel variable? And should I declare cancel volatile? I'm guessing std:atomic_bool will make that unncecessary...

                        class Worker : public QObject
                        {
                            bool getStop() { return cancel; }
                            volatile std::atomic_bool cancel;
                        ...
                        DWORD Worker::copyProgress(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID data)
                        {
                            Worker *worker = static_cast<Worker *>(data);
                            if (worker->getStop())
                                return PROGRESS_CANCEL;
                        
                        kshegunovK 1 Reply Last reply
                        0
                        • C Crag_Hack

                          Will this code maintain the atomicity of the cancel variable? And should I declare cancel volatile? I'm guessing std:atomic_bool will make that unncecessary...

                          class Worker : public QObject
                          {
                              bool getStop() { return cancel; }
                              volatile std::atomic_bool cancel;
                          ...
                          DWORD Worker::copyProgress(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, LARGE_INTEGER, LARGE_INTEGER, DWORD, DWORD, HANDLE, HANDLE, LPVOID data)
                          {
                              Worker *worker = static_cast<Worker *>(data);
                              if (worker->getStop())
                                  return PROGRESS_CANCEL;
                          
                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by kshegunov
                          #63

                          @Crag_Hack said in Non-Reentrant Class Use In Multithreaded Program:

                          Will this code maintain the atomicity of the cancel variable?

                          Yes, of course.

                          And should I declare cancel volatile?

                          No, no reason to do that. Forget volatile, especially if you're not intimately familiar with what it does. It's very special and here there is no a proper reason to use it.

                          I'm guessing std:atomic_bool will make that unncecessary...

                          That is correct. volatile means something quite different anyway, it doesn't provide atomicity at all.

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          1
                          • C Offline
                            C Offline
                            Crag_Hack
                            wrote on last edited by
                            #64

                            Thanks! Almost time to go live!

                            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