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. QThread - moveToThread: Cannot move objects with a parent
Forum Updated to NodeBB v4.3 + New Features

QThread - moveToThread: Cannot move objects with a parent

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 4 Posters 7.0k 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

    @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

    Any ideas?

    I already gave you the answer - don't set a parent or unparent it.

    F Offline
    F Offline
    fem_dev
    wrote on last edited by
    #7

    @Christian-Ehrlicher sorry...I'm not identifying the parent in this case.

    I have 3 elements in this code:

    • QThread
    • Plugin Class
    • Plugin_API Class (Interface)

    I didn't set a parent in any of these 3 elements. You can see it in the code above.

    So:
    1- Who is the parent and the children here?
    2- How can I "don't set a parent"?
    3- How can I "unparent"?

    VRoninV 1 Reply Last reply
    0
    • VRoninV VRonin

      @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

      QObject::moveToThread: Current thread (0x7fa149605d40) is not the object's thread (0x7fa14ae4f3b0).

      Error is pretty clear. If you already moved a plugin to a thread you can't pull it from the thread you put it in and push it into another. moveToThread is push only so only the thread that owns the object can move it to another one

      F Offline
      F Offline
      fem_dev
      wrote on last edited by
      #8

      @VRonin Thank you, but I'm newer in the QThread...and my english is not so good.

      Could you please give me a simple example? May be a pseudo-code or a sequence that I need to do to fix it?

      I appreciate your help and support.

      1 Reply Last reply
      0
      • F fem_dev

        @Christian-Ehrlicher sorry...I'm not identifying the parent in this case.

        I have 3 elements in this code:

        • QThread
        • Plugin Class
        • Plugin_API Class (Interface)

        I didn't set a parent in any of these 3 elements. You can see it in the code above.

        So:
        1- Who is the parent and the children here?
        2- How can I "don't set a parent"?
        3- How can I "unparent"?

        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #9

        @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

        I didn't set a parent in any of these 3 elements. You can see it in the code above.

        Actually the code above is pretty lacking in this sense. we have no information regarding how you fill _pluginStack.

        How can I "unparent"?

        call _pluginStack[step_id]->setParent(nullptr);

        @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

        Could you please give me a simple example? May be a pseudo-code or a sequence that I need to do to fix it?

        It's not clear what you are trying to do here. seems like you are creating a dedicated thread for each plugin but then you try to move those plugins in other threads, hard to give you an example if we don't know what you want to do. In this recent thread there are some examples of working with threads but I'm not 100% sure it applies to your case

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        F 1 Reply Last reply
        4
        • VRoninV VRonin

          @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

          I didn't set a parent in any of these 3 elements. You can see it in the code above.

          Actually the code above is pretty lacking in this sense. we have no information regarding how you fill _pluginStack.

          How can I "unparent"?

          call _pluginStack[step_id]->setParent(nullptr);

          @fem_dev said in QThread - moveToThread: Cannot move objects with a parent:

          Could you please give me a simple example? May be a pseudo-code or a sequence that I need to do to fix it?

          It's not clear what you are trying to do here. seems like you are creating a dedicated thread for each plugin but then you try to move those plugins in other threads, hard to give you an example if we don't know what you want to do. In this recent thread there are some examples of working with threads but I'm not 100% sure it applies to your case

          F Offline
          F Offline
          fem_dev
          wrote on last edited by fem_dev
          #10

          @VRonin I will try to explain better...

          Here is how I load each plugin using QPluginLoader where the input argument called plugins is a list of shared libraries absolute path.

          void job_manager::load_plugins(const QStringList plugins)
          {
              foreach(QString file, plugins) {
          
                  QPluginLoader loader(file);
                  if (loader.load()) {
                      qInfo() << "Loaded: " << loader.fileName();
                      Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
          
                      if (plugin) {
                           // Store plugin in a QMap<std::string, Plugin_API*>
                          _pluginsMap[plugin->getName()] = plugin;
                      } else {
                          qCritical() << "Wrong Plugin API! Could not cast: " << loader.fileName();
                      }
                  } else {
                      qCritical() << "ERROR: " << loader.fileName() << " - Msg: " << loader.errorString();
                  }
              }
          }
          

          In the UI, I have a button called "run". Here is the onClick() action:

          void job_manager::on_run_btn_clicked()
          {
              // ===== Fill the plugin stack vector ===== //
              _numSteps = ui->added_list->count(); // UI execution plugin list. Each plugin is added by the user
              _pluginStack.reserve(_numSteps); // std::vector<Plugin_API*>
          
              for (size_t s = 0; s < _numSteps; s++) {
                  // Get the plugin name:
                  const std::string pluginName = ui->added_list->item(s)->text().toStdString();
          
                  // Store the plugin in a vector. 
                  // I do that because the user can run the same plugin multiple times in a user defined execution sequence.
                  // Always in the serial order
                  _pluginStack[s] = _pluginsMap[pluginName];
              }
          
              callNextPlugin();
          }
          

          So, my _pluginMap can be something like:

          ---------------------
          | ["A"] => Plugin A |
          | ["B"] => Plugin B |
          ---------------------
          

          And, my _pluginStack vector can be something like:

          | 0 | Plugin A |
          | 1 | Plugin A |
          | 2 | Plugin B |
          | 3 | Plugin A |
          

          As you can see above, inside the job_manager::on_run_btn_clicked() method, I call the callNextPlugin().

          void job_manager::callNextPlugin(void)
          {
             if (_currentStep + 1 > _numSteps) { // _current_step start from 0
                 std::cout << "Finished: All done!" << std::endl;
                 return;
             } else {
                 runPlugin(_currentStep);
                 _currentStep++;
             }
          }
          

          And here is the final runPlugin() method:

          void job_manager::runPlugin(const size_t step_id)
          {
              const auto& selectedPlugin = _pluginStack[step_id];
          
              QThread* thread = new QThread;
              selectedPlugin->moveToThread(thread); // Runs Ok for the first time, but I got a error in the second time.
          
              connect(selectedPlugin, &Plugin_API::sendMsg, this, &job_manager::pluginMessage);
              connect(selectedPlugin, &Plugin_API::finished, thread, &QThread::quit);
              connect(selectedPlugin, &Plugin_API::finished, selectedPlugin, &Plugin_API::deleteLater);
              connect(selectedPlugin, &Plugin_API::finished, this, &job_manager::callNextPlugin);
              connect(thread, &QThread::started, selectedPlugin, &Plugin_API::start);
              connect(thread, &QThread::finished, thread, &QThread::deleteLater);
          
              thread->start(QThread::NormalPriority);
          }
          

          So, when one plugin finish your job, the job_manager receives a signal &Plugin_API::finished and it calls the callNextPlugin() method.

          I added the _pluginStack[step_id]->setParent(nullptr); right after the moveToThread() line, but I got the same run-time error.

          QObject::moveToThread: Current thread (0x7fdf56f056e0) is not the object's thread (0x7fdf56e39c80).
          Cannot move to target thread (0x7fdf582ba950)
          
          You might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
          

          Please, could you help me a little bit more? How can I fix it?

          VRoninV 1 Reply Last reply
          0
          • F fem_dev

            @VRonin I will try to explain better...

            Here is how I load each plugin using QPluginLoader where the input argument called plugins is a list of shared libraries absolute path.

            void job_manager::load_plugins(const QStringList plugins)
            {
                foreach(QString file, plugins) {
            
                    QPluginLoader loader(file);
                    if (loader.load()) {
                        qInfo() << "Loaded: " << loader.fileName();
                        Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
            
                        if (plugin) {
                             // Store plugin in a QMap<std::string, Plugin_API*>
                            _pluginsMap[plugin->getName()] = plugin;
                        } else {
                            qCritical() << "Wrong Plugin API! Could not cast: " << loader.fileName();
                        }
                    } else {
                        qCritical() << "ERROR: " << loader.fileName() << " - Msg: " << loader.errorString();
                    }
                }
            }
            

            In the UI, I have a button called "run". Here is the onClick() action:

            void job_manager::on_run_btn_clicked()
            {
                // ===== Fill the plugin stack vector ===== //
                _numSteps = ui->added_list->count(); // UI execution plugin list. Each plugin is added by the user
                _pluginStack.reserve(_numSteps); // std::vector<Plugin_API*>
            
                for (size_t s = 0; s < _numSteps; s++) {
                    // Get the plugin name:
                    const std::string pluginName = ui->added_list->item(s)->text().toStdString();
            
                    // Store the plugin in a vector. 
                    // I do that because the user can run the same plugin multiple times in a user defined execution sequence.
                    // Always in the serial order
                    _pluginStack[s] = _pluginsMap[pluginName];
                }
            
                callNextPlugin();
            }
            

            So, my _pluginMap can be something like:

            ---------------------
            | ["A"] => Plugin A |
            | ["B"] => Plugin B |
            ---------------------
            

            And, my _pluginStack vector can be something like:

            | 0 | Plugin A |
            | 1 | Plugin A |
            | 2 | Plugin B |
            | 3 | Plugin A |
            

            As you can see above, inside the job_manager::on_run_btn_clicked() method, I call the callNextPlugin().

            void job_manager::callNextPlugin(void)
            {
               if (_currentStep + 1 > _numSteps) { // _current_step start from 0
                   std::cout << "Finished: All done!" << std::endl;
                   return;
               } else {
                   runPlugin(_currentStep);
                   _currentStep++;
               }
            }
            

            And here is the final runPlugin() method:

            void job_manager::runPlugin(const size_t step_id)
            {
                const auto& selectedPlugin = _pluginStack[step_id];
            
                QThread* thread = new QThread;
                selectedPlugin->moveToThread(thread); // Runs Ok for the first time, but I got a error in the second time.
            
                connect(selectedPlugin, &Plugin_API::sendMsg, this, &job_manager::pluginMessage);
                connect(selectedPlugin, &Plugin_API::finished, thread, &QThread::quit);
                connect(selectedPlugin, &Plugin_API::finished, selectedPlugin, &Plugin_API::deleteLater);
                connect(selectedPlugin, &Plugin_API::finished, this, &job_manager::callNextPlugin);
                connect(thread, &QThread::started, selectedPlugin, &Plugin_API::start);
                connect(thread, &QThread::finished, thread, &QThread::deleteLater);
            
                thread->start(QThread::NormalPriority);
            }
            

            So, when one plugin finish your job, the job_manager receives a signal &Plugin_API::finished and it calls the callNextPlugin() method.

            I added the _pluginStack[step_id]->setParent(nullptr); right after the moveToThread() line, but I got the same run-time error.

            QObject::moveToThread: Current thread (0x7fdf56f056e0) is not the object's thread (0x7fdf56e39c80).
            Cannot move to target thread (0x7fdf582ba950)
            
            You might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
            

            Please, could you help me a little bit more? How can I fix it?

            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #11

            I added the _pluginStack[step_id]->setParent(nullptr); right after the moveToThread() line, but I got the same run-time error.

            It should be added before


            This running through workers is exactly the case described in the topic linked above, have a look at the last 2 examples to avoid unecessary operations

            QObject::moveToThread: Current thread (0x7fdf56f056e0) is not the object's thread (0x7fdf56e39c80).

            This error is saying that you called moveToThread on that plugin already. The main thread (0x7fdf56f056e0) sent the object to a secondary thread (0x7fdf56e39c80) already so it can't send it to 0x7fdf582ba950. only 0x7fdf56e39c80 can send the object to 0x7fdf582ba950

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            F 1 Reply Last reply
            0
            • VRoninV VRonin

              I added the _pluginStack[step_id]->setParent(nullptr); right after the moveToThread() line, but I got the same run-time error.

              It should be added before


              This running through workers is exactly the case described in the topic linked above, have a look at the last 2 examples to avoid unecessary operations

              QObject::moveToThread: Current thread (0x7fdf56f056e0) is not the object's thread (0x7fdf56e39c80).

              This error is saying that you called moveToThread on that plugin already. The main thread (0x7fdf56f056e0) sent the object to a secondary thread (0x7fdf56e39c80) already so it can't send it to 0x7fdf582ba950. only 0x7fdf56e39c80 can send the object to 0x7fdf582ba950

              F Offline
              F Offline
              fem_dev
              wrote on last edited by
              #12

              @VRonin I tried to put the _pluginStack[step_id]->setParent(nullptr); before the moveToThread() too, but i got the same error message.

              I will try to look better the topic that you send to me.

              If I have doubts, I will come back here, ok?

              CP71C 1 Reply Last reply
              0
              • F fem_dev

                @VRonin I tried to put the _pluginStack[step_id]->setParent(nullptr); before the moveToThread() too, but i got the same error message.

                I will try to look better the topic that you send to me.

                If I have doubts, I will come back here, ok?

                CP71C Offline
                CP71C Offline
                CP71
                wrote on last edited by
                #13

                @fem_dev
                Hi,
                how our colleagues have already said a object has a parent which lives in the current thread so it cannot be moved!

                I don’t understand why you wrote:
                const auto& selectedPlugin = _pluginStack[step_id];

                instead of
                auto& selectedPlugin = _pluginStack[step_id];

                https://www.programming-books.io/essential/cpp/auto-const-and-references-b0a629204f0a4ed6a8b4b02f30835c31

                I'm wondering why the first instance runs well and then fail, or it seems so.
                What difference are there? If I'd be you I'd try to find the differences between two plugins creation.

                F 1 Reply Last reply
                0
                • VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #14

                  if we want to be picky then connect(selectedPlugin, &Plugin_API::finished, selectedPlugin, &Plugin_API::deleteLater); will cause _pluginsMap to contain dangling pointers (unless it's a QMap<QString, QPointer<Plugin_API> > then it's just null pointers)

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  F 1 Reply Last reply
                  2
                  • CP71C CP71

                    @fem_dev
                    Hi,
                    how our colleagues have already said a object has a parent which lives in the current thread so it cannot be moved!

                    I don’t understand why you wrote:
                    const auto& selectedPlugin = _pluginStack[step_id];

                    instead of
                    auto& selectedPlugin = _pluginStack[step_id];

                    https://www.programming-books.io/essential/cpp/auto-const-and-references-b0a629204f0a4ed6a8b4b02f30835c31

                    I'm wondering why the first instance runs well and then fail, or it seems so.
                    What difference are there? If I'd be you I'd try to find the differences between two plugins creation.

                    F Offline
                    F Offline
                    fem_dev
                    wrote on last edited by
                    #15

                    @CP71 There's no difference. You are right.

                    1 Reply Last reply
                    1
                    • VRoninV VRonin

                      if we want to be picky then connect(selectedPlugin, &Plugin_API::finished, selectedPlugin, &Plugin_API::deleteLater); will cause _pluginsMap to contain dangling pointers (unless it's a QMap<QString, QPointer<Plugin_API> > then it's just null pointers)

                      F Offline
                      F Offline
                      fem_dev
                      wrote on last edited by
                      #16

                      @VRonin Yes...I think that this is my problem. Thank you!

                      1 Reply Last reply
                      1

                      • Login

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