QVariantMap/QObject store bag



  • To store settings of application with multithreaded plugins I want create a class something like this:

    @class VariantSettings : QVariantMap, QObject
    {
    public slots:
    void storeVariant( QString name, QVariant value );
    void retrieveVariant( QString name );
    signals:
    void valueVariant( QVariant value );
    }@

    Slots and signals have to be connected via Qt::AutoConnection to safely deliver values if sender and receiver are in different threads. Received in storeVariant() value it just stores in it's QMap. If it receives request in retrieveVariant() then it sends signal valueVariant() with stored value. Probably all must work fine but I just want ask somebody who did same before - can I wait something unexpected. Are there any "underwater rocks" in this design?

    I just did not ever used QMap before and as I see it is not a QObject. May be there is some reason to not make such a solution, is there?



  • Why do you want to inherit from QVariantMap? Your class could simply encapsulate one instead. That would get rid of the multiple inheritance and hide what is basically an implementation detail anyway. And, you need to inherit publicly from QObject of course.

    Apart from that, sure, it could work I think. Not sure if the design is all that pretty, but then again, I don't know your requirements.



  • bq. Why do you want to inherit from QVariantMap?

    QMap is a superclass, therefore I don't see where from "rhombus" inheritance can appear.



  • Not clearly relative to this topic question: Can QVariantMap entirely be sent through slot connection? I do not want send pointer to it (because of threading). And do not want send it's content "line by line".



  • I wouldn't inherit from QVariantMap either; just encapsulate one - as Andre said.
    It's not about beeing not possible it's about good class design.

    Just be sure to properly guard your accesses with mutexes or read/write locks as containers are reentrant but not threadsafe.



  • [quote author="Gourmand" date="1311928472"]bq. Why do you want to inherit from QVariantMap?

    QMap is a superclass, therefore I don't see where from "rhombus" inheritance can appear.
    [/quote]
    I did not say that such an inheritance structure does appear, I just asked why you think your class should inherit from QVariantMap. Because based on what you told us in your opening post, it doesn't seem to be needed, and can potentially be dangerous due to the fact that QVariantMap does not have a virtual destructor.

    [quote author="Gourmand" date="1311928938"]Not clearly relative to this topic question: Can QVariantMap entirely be sent through slot connection? I do not want send pointer to it (because of threading). And do not want send it's content "line by line".[/quote]
    Yes, that is possible. Possibly not cheap, but possible. But why would you want to do that? You were just showing us methods to access individual data points, and I thought the whole point was to do that thread save.



  • bq. I just asked why you think your class should inherit from QVariantMap.

    Ok, this allows access to settings inside plugin just like this:

    @VariantSettings settings;
    ...
    int somenumber = settings[ "somenumber" ];
    QString somestring = settings[ "somestring" ];@
    ... so on

    But in main application settings are accessed using signals/slot. Reason is: main application stores and edits settings for all plugins (it automatically creates settings dialogs for all loaded plugins), but plugins use those settings.

    bq. But why would you want to do that?

    I just told that this is Not clearly relative to this topic question



  • bq. can potentially be dangerous due to the fact that QVariantMap does not have a virtual destructor

    I see it is declared like this:

    @typedef QMap<QString, QVariant> QVariantMap;@

    exactly it is a QMap which has virtual destructor.



  • [quote author="Gourmand" date="1311933819"][quote] can potentially be dangerous due to the fact that QVariantMap does not have a virtual destructor[/quote]

    I see it is declared like this:

    @typedef QMap<QString, QVariant> QVariantMap;@

    exactly it is a QMap which has virtual destructor.[/quote]

    Really? Is QMap's destructor virtual? In the source code I have here, it looks like this:

    @
    template <class Key, class T>
    class QMap
    {
    typedef QMapNode<Key, T> Node;
    typedef QMapPayloadNode<Key, T> PayloadNode;

    // (...)
    public:
    inline QMap() : d(&QMapData;::shared_null) { d->ref.ref(); }
    inline QMap(const QMap<Key, T> &other;) : d(other.d)
    { d->ref.ref(); if (!d->sharable) detach(); }
    inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); }
    //(...)
    }
    @

    Doesn't look all that virtual to me...

    [quote author="Gourmand" date="1311933502"][quote] I just asked why you think your class should inherit from QVariantMap.[/quote]

    Ok, this allows access to settings inside plugin just like this:

    @VariantSettings settings;
    ...
    int somenumber = settings[ "somenumber" ];
    QString somestring = settings[ "somestring" ];@
    ... so on

    But in main application settings are accessed using signals/slot. Reason is: main application stores and edits settings for all plugins (it automatically creates settings dialogs for all loaded plugins), but plugins use those settings.[/quote]
    So, if I understand you correctly, it is just because in your class implementation, you don't want to type things like this:
    @VariantSettings settings;
    ...
    int somenumber = m_valueMap.settings[ "somenumber" ];
    QString somestring = m_valueMap.settings[ "somestring" ];
    @

    OK, I guess that could be an argument, but IMHO, not a good one.

    [quote][quote]But why would you want to do that?[/quote]
    I just told that this is Not clearly relative to this topic question
    [/quote]
    OK, so I misunderstood. It is probably wise though not to confuse a topic with irrelevant side-questions if you want a clear answer.



  • [quote author="Gourmand" date="1311933502"]
    Ok, this allows access to settings inside plugin just like this:

    @
    VariantSettings settings;
    ...
    int somenumber = settings[ "somenumber" ];
    QString somestring = settings[ "somestring" ];@
    [/quote]

    QMap and so QVariantMap is reentrant, not threadsafe. If you expose any of the QMap interface your resulting class will also be reentrant, not threadsafe.

    If you like to provide such functionality you will have to provide your own thread-safe index operator.



  • @QMap and so QVariantMap is reentrant, not threadsafe. If you expose any of the QMap interface your resulting class will also be reentrant, not threadsafe.

    If you like to provide such functionality you will have to provide your own thread-safe index operator.@

    I will use QMutex protection of course.

    @you don’t want to type things like this:

    VariantSettings settings;
    ...
    int somenumber = m_valueMap.settings[ "somenumber" ];
    QString somestring = m_valueMap.settings[ "somestring" ];
    @

    this should be

    @int somenumber = settings.m_valueMap[ "somenumber" ];
    QString somestring = settings.m_valueMap[ "somestring" ];@

    indeed.

    Yes I don't want. And this is for plugins which can be developed by other people, not only me. I want remove any extra essence if it is not necessary.

    @Doesn’t look all that virtual to me…@

    Hm, exactly... But does this really matter in my case?



  • [quote author="Gourmand" date="1311938674"][quote]Doesn’t look all that virtual to me…[/quote]

    Hm, exactly... But does this really matter in my case?
    [/quote]
    Yes. A plugin could do this:

    @
    QVariantMap* theValues = new VariantSettings(this);
    // ...
    delete theValues; //undefined behaviour!
    @

    [quote author="Gourmand" date="1311938674"]
    [quote]you don’t want to type things like this:
    @
    VariantSettings settings;
    ...
    int somenumber = m_valueMap.settings[ "somenumber" ];
    QString somestring = m_valueMap.settings[ "somestring" ];
    @
    [/quote]

    this should be

    @
    int somenumber = settings.m_valueMap[ "somenumber" ];
    QString somestring = settings.m_valueMap[ "somestring" ];
    @

    indeed.

    Yes I don't want. And this is for plugins which can be developed by other people, not only me. I want remove any extra essence if it is not necessary.
    [/quote]
    I guess I misunderstood where those lines would occur. I interpretted them as being inside of the VariantSettings class itself. Obviously you would not do what you show in your second example; that would be just as bad or worse as multiple inheritance and at the very least very ugly.

    What I would do is hide the actual storage mechanism. Instead, you provide your own API that you make save for use across threads. It could follow the API that is there for QMap if you like. Note that you can not override the methods of QMap anyway, as none of them are virtual.

    Finally: please don't use code tags where you are quoting others. It is confusing, leads to ugly-formatted posts and makes replying harder. Quotes can be nested, though the bq. doesn' t work that way (forum bug).



  • [quote author="Gourmand" date="1311938674"]Hm, exactly... But does this really matter in my case?[/quote]

    Not as long as you are aware that your destructor won't be called if the object is deleted through a base class pointer.

    However, you create code that is broken by design, and "anything that can go wrong will go wrong".



  • bq. Yes. A plugin could do this:

    @QVariantMap* theValues = new VariantSettings(this);
    // ...
    delete theValues; //undefined behaviour!@

    No, it could not. The VariantSettings object is a property of plugin class. Accessed not by pointer but as field of plugin class. The plugin inherits "plugin interface" of course. Even settings object can be a property of interface class. No other settings object will be defined for plugin ever. One plugin - one VariantSettings object. It will be destroyed with plugin object. No virtual destructor needed.



  • Fine. If you are so certain about your design, then why come here and ask for advice on it in the first place? It is hard to give you good advice based on the bits and pieces of information that you are actually providing, and at least for me, my mental image of what you are trying to achieve has shifted with each of your posts.

    So: have fun. Go ahead and implement it all in the way you outlined here. I hope it proves to be smooth sailing for you.



  • bq. If you are so certain about your design, then why come here and ask for advice on it in the first place?

    Because I need to somebody help me find possible troubles which I cannot see. I told - I did not use QMap before.

    Thanx for advices. All was helpful.


Log in to reply
 

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