Problem with Singleton: Why isn't it unique?



  • I want to define a Singleton component as a dispatcher of signals. For example, I to call a function on the Singleton from somewhere in a QML file (let's say function1()) and emit a signal from inside that Singleton (let's say mySignal()).

    I should then be able to connect to the signal from another QML file completely.

    I'll upload a simple example tomorrow that shows this. It does work as expected.

    But then when I implement that functionality in another codebase, the second QML component is not able to receive the signal from the singleton. When I print the singleton, I get different "addresses":

    qml: ### ActionSingleton.qml -- this:            ActionSingleton_QMLTYPE_71(0x14e5a10)
    qml: ### OtherComponent.qml  -- ActionSingleton: ActionSingleton_QMLTYPE_89(0x31b2f20)
    

    I expected both to print the same values (the simple example does print the same value).

    My code is different from the minimal, simple example, but I don't what could be that different. I mean, a singleton should be a singleton, however the code is organized? I do have a pthread in the code for another event loop (for network communications). Could that be interfering? I'm also using cmake (version qmake on the simple example).

    I'm really out of ideas! Any suggestions?

    Thanks!



  • Hi! Please post a minimal yet complete example so others can reproduce this / see what's going wrong.



  • @Wieland Sorry I had to leave yesterday and even had to rush the post.

    Here's a minimal working example:
    https://github.com/nbigaouette/qml-singleton-issue
    (see tag minimal_working_example at commit 5fb24ab84c0f969ddba5973acf7bbaff4ae717c9 for the working version).

    Actually, it contains a working example showing what I want to achieve. The problem is that when I integrate this into my codebase, it does not work anymore; I have multiple singleton! I'll try to modify the working example in a way to "break" it and show the same (wrong) behaviour.

    Meanwhile, do you have an idea as to why a singleton might have multiple instances? Could threading creating a second one? Anything else?

    Thanks!



  • Playing with the example code I was able to identify the issue.

    The minimal_working_example contains the simplest, working example of what I want to achieve.

    In the problematic branch I added the different modifications required to make the code look exactly the way it was done in the "real" code base, one small commit at a time.

    After a while, I realized that the MyComponentOne.qml and MyComponentTwo.qml's Connections stopped working: those components could not receive the func2 signal emitted by the singleton (even if there was no error): The signal handlers onFunc2 defined in the MyComponentOne.qml and MyComponentTwo.qml are never receiving any signals!

    Thanks to git bisect, I identified commit 5b1db19a47192b78bb49f773b213ca5c29e2f6eb as the bad one:

    git show 5b1db19a47192b78bb49f773b213ca5c29e2f6eb
    commit 5b1db19a47192b78bb49f773b213ca5c29e2f6eb
    Author: Nicolas Bigaouette <nbigaouette@gmail.com>
    Date:   Fri Jun 17 10:03:11 2016 -0400
    
        Use "///" instead of "/" when loading main.qml
    
    diff --git a/simple/src/main.cpp b/simple/src/main.cpp
    index 21e3b00..1424282 100644
    --- a/simple/src/main.cpp
    +++ b/simple/src/main.cpp
    @@ -6,7 +6,7 @@ int main(int argc, char *argv[])
         QGuiApplication app(argc, argv);
     
         QQmlApplicationEngine engine;
    -    engine.load(QUrl("qrc:/qml/main.qml"));
    +    engine.load(QUrl("qrc:///qml/main.qml"));
     
         return app.exec();
     }
    

    After that commit, I did:

    1. Compile and run
    2. Click blue rectangle (load MyComponentOne.qml)
    3. Click cyan rectangle (call MySingleton.func1())
    4. Click red rectangle (load MyComponentTwo.qml)
    5. Click cyan rectangle (call MySingleton.func1())

    and the output is as follow:

    qml: # MySingleton.qml::func1()      - MySingleton: MySingleton_QMLTYPE_0(0x224dd10)
    qml: # MySingleton.qml::onFunc2()    - MySingleton: MySingleton_QMLTYPE_0(0x224dd10)
    qml: # MySingleton.qml::func1()      - MySingleton: MySingleton_QMLTYPE_0(0x224dd10)
    qml: # MySingleton.qml::onFunc2()    - MySingleton: MySingleton_QMLTYPE_0(0x224dd10)
    

    Note how onFunc2 is only triggered for the singleton and not for the MyComponent*.qml.

    After reverting 5b1db19a47192b78bb49f773b213ca5c29e2f6eb (resulting in adcfaa35d1ec3546b4d2a2d4494bc01c0cc63983) I get the proper behaviour:

    qml: # MySingleton.qml::func1()      - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    qml: # MySingleton.qml::onFunc2()    - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    qml: # MyComponentOne.qml::onFunc2() - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    qml: # MySingleton.qml::func1()      - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    qml: # MySingleton.qml::onFunc2()    - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    qml: # MyComponentTwo.qml::onFunc2() - MySingleton: MySingleton_QMLTYPE_0(0x25a3810)
    

    So the problem was how the main.qml file is loaded from C++!

    Wrong:

    engine.load(QUrl("qrc:///qml/main.qml"));
    

    Good:

    engine.load(QUrl("qrc:/qml/main.qml"));
    

    I don't know why the code was using "///" instead of "/"...


Log in to reply
 

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