How to manage QObject instance which is shared among lots of C++/QML places



  • Suppose I have an QObject-derived instance.

    If I have to share this instance in C++, I'll use QSharedPointer or std::shared_ptr.
    If I have to share this instance in QML, I'll set the ownership to JavascriptOwnership and let the QML engine manage it.

    However, now I have to share this instance in both of C++ and QML.
    I cannot set JavascriptOwnership because this instance should be alive while used in C++.
    I cannot use QSharedPointer because once I expose raw pointer encapsualted in QSharedPointer to QML, reference-counting makes no more sense.

    How should I manage such instance?


  • Moderators

    @xylosper
    you could use the same approach like Qt's implicit sharing.
    The wrapper class can be created multiple times. Each wrapper class holds an shared pointer to the actual data. (make sure you implement the copy constructor and assignment operator).


  • Qt Champions 2016

    @xylosper said in How to manage QObject instance which is shared among lots of C++/QML places:

    If I have to share this instance in C++, I'll use QSharedPointer or std::shared_ptr.

    You shouldn't do that even from C++. A shared pointer holds an instance to an object that manages its own lifetime and QObjects don't! Their lifetime is either managed by their parent or manually by you. You should either use QScopedPointer or QPointer depending on the situation.

    As a side note you can't use implicit sharing with QObjects as @raven-worx suggested. That'd be no different than holding it in QSharedPointer

    If you need it to persist throughout I'd parent it to the application object and register it as a global object for QML before the engine starts up. However you should elaborate on the lifetime of said object, when should it be created and when should it be destroyed?



  • @raven-worx

    If I write a wrapper class. doesn't it mean that I have to write duplicated slots/signals?

    @kshegunov

    You shouldn't do that even from C++. A shared pointer holds an instance to an object that manages its own lifetime and QObjects don't! Their lifetime is either managed by their parent or manually by you. You should either use QScopedPointer or QPointer depending on the situation.

    Why not? It's just a pointer to an object. All my instances does not have a parent.
    It's derived from QObject only for signal.
    Even if it has a parent, Qt will remove the child information automatically in child list of parent when the instance deleted at outside of parent's dtor. Or, may I miss something here..?

    If you need it to persist

    Nope, my instance is not permanent. It can be created in both of C++ and QML and also can be deleted in both of C++ and QML.
    Also, it is not a unique one. It cannot be a singletone.


  • Moderators

    @xylosper said in How to manage QObject instance which is shared among lots of C++/QML places:

    If I write a wrapper class. doesn't it mean that I have to write duplicated slots/signals?

    Do the connection (signal forwarding) in the copy constructor and assignment operator. Since you anyway want to use it in QML you can use the automatic property binding (declare a Q_PROPERTY in the wrapper class).

    @kshegunov
    i also don't see where the problem is? Just by using a QObject instance doesnt mean that you have to put it an parent-child-relationship.


  • Qt Champions 2016

    @xylosper, @raven-worx
    https://forum.qt.io/topic/74147/share-qstring-between-threads
    It includes links to the mailing list with more information. Basically the problem is you can't guarantee the time of destruction of the object (implying multithreading here), which in turn leads to the possibility of having a queued event that is handled by a deleted QObject. The result is a cryptic segfault in the event loop processing.


  • Moderators

    @kshegunov
    yes, but where is the threading involved here?


  • Qt Champions 2016

    @raven-worx said in How to manage QObject instance which is shared among lots of C++/QML places:

    @kshegunov
    yes, but where is the threading involved here?

    Doesn't QML employ threads internally? I might be wrong, but I thought it did.


  • Moderators

    @kshegunov
    AFAIK it runs on the GUI thread


  • Qt Champions 2016

    @raven-worx
    Fair enough. If that's the case, my comment can be disregarded.



  • @kshegunov

    Doesn't QML employ threads internally? I might be wrong, but I thought it did.

    Yes, generally, QML runs on both of main GUI thread and scene graph rendering thread.
    But the rendering thread won't appear unless you're writing some custom rendering items.
    Things unrelated with rendering, all QML codes run on GUI thread, and my object lives in GUI thread only.
    FYI, please see Threaded Render Loop ("threaded") section from here http://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph.html
    Thank you.

    @raven-worx

    Do the connection (signal forwarding) in the copy constructor and assignment operator. Since you anyway want to use it in QML you can use the automatic property binding (declare a Q_PROPERTY in the wrapper class).

    Yes, I can do it. It makes me omit duplicated implementation but still, I need to copy the interfaces(signals/slots/Q_INVOKABLEs).
    But it seems that that's the only workaround. Thank you.


  • Moderators

    @xylosper
    you could also try to register a singleton type.

    In your case the static singleton provider would look like something this:

    MySingleTonType* g_SingletonTypeInstance = 0; // global or static instance
    
    static QObject *example_qobject_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
    {
          if( g_SingletonTypeInstance == 0 )
               g_SingletonTypeInstance = new MySingleTonType;
         return g_SingletonTypeInstance;
    }
    


  • @raven-worx

    Unfortunately, singleton is my option. Although I said 'an' instance only for example, the class could be instantiated several times. Sorry for incorrect discription.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.