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. Can you help me to find where my object is living?
Forum Updated to NodeBB v4.3 + New Features

Can you help me to find where my object is living?

Scheduled Pinned Locked Moved General and Desktop
7 Posts 2 Posters 2.4k 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.
  • T Offline
    T Offline
    tlvju
    wrote on last edited by
    #1

    Hi,

    Yesterday I encountered an interesting scenario that I would like to discuss with you.

    To describe it as easy as possible I made a small example of that scenario.

    Let's first explain it:
    I have three objects MainWindow, MyObject1 and MyObject2.

    From the MainWindow I create MyObject1.
    MyObject1 is moved to its own thread, let's call it MyThread.
    Signal/Slots connections are done to well clean MyThread when MyObject1 is deleted.
    => MyObject1 is living in MyThread.

    MyObject2 is a single tone object, and have a method startMyObject2Timer which start a timer with a period of 1 second.
    => MyObject2 is living in MyThread.

    After 5 seconds MyObject2 is deleted, done from QMainWindow.
    This trigger MyThread to also be deleted.

    Results:
    The timer in MyObject2 is not timing out anymore.

    Question:
    Where is living MyObject2 since the thread where he was living has been deleted?

    Here is the code of that scenario:
    MainWindow
    @
    #include <QDebug>
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    qDebug() << this->metaObject()->className() << __func__ << "THREAD :" << QThread::currentThreadId();
    
    m_object1 = new MyObject1();
    QThread *thread1 = new QThread();
    m_object1->moveToThread(thread1);
    connect (thread1, SIGNAL(started()), m_object1, SLOT(process()));
    connect (m_object1, SIGNAL(destroyed()), thread1, SLOT(quit()));
    connect (thread1, SIGNAL(finished()), this, SLOT(onThreadFinished()));
    connect (thread1, SIGNAL(finished()), thread1, SLOT(deleteLater()));
    thread1->start();
    
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    m_timer.start(5000);
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::onTimeout()
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();

    if (m_object1 != NULL)
    {
        delete m_object1;
        m_object1 = NULL;
    }
    

    }

    void MainWindow::onThreadFinished()
    {
    qDebug() << this->metaObject()->className() << func;
    }
    @

    MyObject1
    @
    #include <QDebug>

    #include "myobject1.h"
    #include "myobject2.h"

    MyObject1::MyObject1(QObject *parent) :
    QObject(parent)
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();
    }

    MyObject1::~MyObject1()
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();
    }

    void MyObject1::process()
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();

    MyObject2::instance()->startMyObject2Timer();
    

    }

    #ifndef MYTHREAD1_H
    #define MYTHREAD1_H

    #include <QThread>
    #include <QTimer>
    #include <QTcpSocket>
    #include "myobject2.h"

    class MyObject1 : public QObject
    {
    Q_OBJECT
    public:
    explicit MyObject1(QObject *parent = 0);
    ~MyObject1();

    signals:

    public slots:
    void process();

    protected:

    private:
    };

    void CbTest(void);

    #endif // MYTHREAD1_H
    @

    MyObject2
    @
    #include <QDebug>
    #include <QThread>
    #include "myobject2.h"

    MyObject2::MyObject2(QObject *parent) :
    QObject(parent)
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();
    }

    MyObject2::~MyObject2()
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();
    }

    void MyObject2::startMyObject2Timer()
    {
    m_timer = new QTimer();
    m_timer->setInterval(1000);
    connect (m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    m_timer->start();
    }

    void MyObject2::onTimeout()
    {
    qDebug() << this->metaObject()->className() << func << "THREAD :" << QThread::currentThreadId();
    }

    #ifndef MYOBJECT2_H
    #define MYOBJECT2_H

    #include <QTimer>
    #include <QObject>

    class MyObject2 : public QObject
    {
    Q_OBJECT
    public:
    static MyObject2* instance()
    {
    static MyObject2* m_myObject2 = NULL;
    if (m_myObject2 == NULL)
    {
    m_myObject2 = new MyObject2();
    }
    return m_myObject2;
    }
    ~MyObject2();

    void startMyObject2Timer();
    

    signals:

    public slots:
    void onTimeout(void);

    protected:

    private:
    explicit MyObject2(QObject *parent = 0);

    QTimer *m_timer;
    

    };

    #endif // MYOBJECT2_H

    @

    1 Reply Last reply
    0
    • C Offline
      C Offline
      code_fodder
      wrote on last edited by
      #2

      Hi tlvju,

      Maybe I missed it, but I do not see where *m_object2 is instantiated. You have the declration:

      @private:
      MyObject2 *m_object2;@

      In MyObject1, but it is never set to anything... there is no m_object = new MyObject2(...);

      Is this intentional?, maybe this is to do with the issue? - if you instantiate it within the process() function (which I assume is only called once after the thread is started) then it will be instantiated within the thread that Object1 is running in.

      Do you have the output to your code showing all the thread IDs and the constructor and destructor function calls?

      • EDIT -

      Oh wait... I see it now, you have this static function and object within MyObject2 and you call it with "instance" function to return the pointer to the object.

      However, since you created/instantiated the MyObject2 instance within MyObject1, which in turn is within thread1, then the instance of MyObject2 will be within thread1.

      So when you stop thread1 the instance of MyObject2 will no longer be running (even if it is not deleted properly).

      An object is instantiated within the thread that calls the code to instantiate it, in this case thread1.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        tlvju
        wrote on last edited by
        #3

        Hi code_fodder,

        MyObject2 is a single tone object, and it is created from MyObject1 process function by calling the static function MyObject2::instance().

        Here is the output of the code:
        @
        MainWindow MainWindow THREAD : 0x3a8
        MyObject1 MyObject1 THREAD : 0x3a8
        MyObject1 process THREAD : 0x1218
        MyObject2 MyObject2 THREAD : 0x1218
        MyObject2 onTimeout THREAD : 0x1218
        MyObject2 onTimeout THREAD : 0x1218
        MyObject2 onTimeout THREAD : 0x1218
        MyObject2 onTimeout THREAD : 0x1218
        MainWindow onTimeout THREAD : 0x3a8
        MyObject1 ~MyObject1 THREAD : 0x3a8
        MainWindow onThreadFinished
        @

        1 Reply Last reply
        0
        • C Offline
          C Offline
          code_fodder
          wrote on last edited by
          #4

          yes... this looks exactly as it should. MyObject2 is within thread1 (see my - EDIT -), I missed the instance() call and updated my post for it...

          Still, you should remove the *m_object2 member if its not used : )

          1 Reply Last reply
          0
          • T Offline
            T Offline
            tlvju
            wrote on last edited by
            #5

            It's tricky scenario, and I wanted to know the proper way of handling it.

            Indeed MyObject2 is a single tone object, in that case the first object which will call the instance method of MyObject2 will create it. Then MyObject2 will live in the context of his creator.

            What can be done is to move MyObject2 in its own thread, or call the instance method from a place where the thread attached to it will not be deleted.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              code_fodder
              wrote on last edited by
              #6

              It needs to be instantiated in a thread that will not be deleted.... as you say, maybe its own thread.

              Somthing like (written by hand, so forgive any errors):
              @
              SingletonObj *sObj = new SingletonObj();
              QThread *signletonThread = new QThread();
              sObj->moveToThread(signletonThread);
              QObject::connect(signletonThread, SIGNAL(started()), SingletonObj, SLOT(run()));
              signletonThread->start();
              // Then implement run() within SingletonObj to do its startup stuff...
              @

              Do that in MainWindow() constructor. Remember, do NOT call functions directly from you class otherwise anything that is instantiated within the class will live in the calling thread :o

              Then the best way to access the singleton object would be via signals/slots. Its not really safe to have a pointer to an object that lives in a different thread. There must be some very specific reason to do that. If you have one please explain it :)

              Otherwise, this "singleton" can just sit there in its own thread quite happily, and answer slot/signal calls to it.

              1 Reply Last reply
              0
              • T Offline
                T Offline
                tlvju
                wrote on last edited by
                #7

                Thanks for your reply, I will choose which way of handling that scenario.

                Regards.

                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