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. Moving object back to parent thread

Moving object back to parent thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 2 Posters 799 Views
  • 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.
  • R Offline
    R Offline
    ruvim
    wrote on last edited by
    #1

    Hello,
    I am writing application communicating with serial devices.
    Currently I am having my custom SerialDeviceManager object which stores open connections to serial devices that I am working with (might be multiple devices). After user choices device(s) that he is interested to communicate with, I am creating SerialDeviceWrapper objects that have some communication logic and move them to separate threads together with QSerialPort objects.
    Simplified code:

    QMap<int, QSerialPort*> devices; // Initialized earlier and stores open connections
    QMap<int, QPair<SerialDeviceWrapper*, QThread*> > active_devices; // Stores initialized threads
    for (auto& dev_id : dev_ids) // dev_ids comes from user choice
    {
         SerialDeviceWrapper *sdw = new SerialDeviceWrapper(devices[dev_id]);
         QThread *device_thread = new QThread();
         sdw->moveToThread(device_thread);
         devices[dev_id]->moveToThread(device_thread);
         connect(device_thread, &QThread::finished, sdw, &QObject::deleteLater);
         connect(device_thread, &QThread::finished, device_thread, &QObject::deleteLater);
         device_thread->start();
         active_devices.insert(dev_id, qMakePair(sdw, device_thread));
    }
    

    Then upon some events I am invoking slots of created SerialDeviceWrapper's:

    // from thread where SerialDeviceManager lives
    // int device_id; uint8_t arg1, arg2 coming from event
    QMetaObject::invokeMethod(active_devices[device_id].first, "SlotName", Qt::QueuedConnection, Q_ARG(const uint8_t, arg1), Q_ARG(const uint8_t, arg2));
    

    Also if user decides that he doesn't need certain serial device anymore, I am stopping SerialDeviceWrapper thread

    // int device_id coming from event
    active_devices[device_id].second->quit();
    active_devices[device_id].second->wait();
    // connected deleteLater will dispose wrapper object and thread object someday
    

    However I do not want to close QSerialPort for this device as it might be reused again by user later.
    My question is how/when should I correctly move QSerialPort object that were moved to Wrapper's QThread back to thread where SerialDeviceManager lives?
    Probably it is possible to do nothing and in case user decides to reuse serial device try to pull QSerialPort object to SerialDeviceManager's thread from itself first (as stopped thread will be deleted and QSerialPort object won't have any thread assigned to it and from documentation "objects with no thread affinity can be "pulled" to the current thread"). But in such case is scenario "User stops serial device communication -> User decides to reuse serial device" but deleteLater for stopped thread is not invoked yet (so QSerialPort still belongs to this thread affinity) is possible?

    Thanks in advance for helping!

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

      Hi,

      You could have a released signal with a pointer to a QSerialPort object as parameter that you connect to your manager so you can put that serial port back to the free pool and the manager's thread.

      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
      • R Offline
        R Offline
        ruvim
        wrote on last edited by ruvim
        #3

        Hi, SGaist,
        Thanks for reply! But at what point of SerialDeviceWrapper's lifecycle shoult I emit released signal? As far as I understand, it should be emitted somewhere after QThread::finished signal to be sure that it will be placed in event loop after deleteLater for thread that QSerialPort was in.

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

          One way could be that rather than calling deleteLater when you thread finishes, you call a slot on the manager to do the cleanup.

          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
          • R Offline
            R Offline
            ruvim
            wrote on last edited by
            #5

            Thanks for helping, SGaist!

            At the end I changed

            connect(device_thread, &QThread::finished, device_thread, &QObject::deleteLater);
            

            to

            connect(device_thread, &QThread::finished, this, [this, dev_id](){ this->DeleteActiveDevice(dev_id); });
            

            and added slot

            void SerialDeviceManager::DeleteActiveDevice(const int dev_id)
            {
                delete active_devices[dev_id].second;
                active_devices.remove(dev_id);
                // At this point serial port connection will be with no thread affinity
                devices[dev_id]->moveToThread(QThread::currentThread());
            }
            
            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