[Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

Ulf Hermann ulf.hermann at qt.io
Mon Oct 23 17:38:22 CEST 2023


> The question though is whether this would be a singleton per qmlengine. 
> If it will, then that's a nogo as the list of loaded fonts needs to 
> exist once regardless of how much engines are running

Singletons are created once per engine, even C++ ones. You should not 
subvert this. And you cannot safely share JavaScript objects across 
engines anyway.

What you _can_ do is have your SingletonBase redirect the property 
access to some other place that holds a unique list of font families. 
You can write the getter for a Q_PROPERTY any way you like after all. If 
you have a QList<QString> for the font families, redirecting through one 
more function call is not a big performance hit, due to implicit 
sharing. And since your actual access to the font families is via the 
QML-defined property, each engine will access the original font families 
only once. So:

// singletonbase.h
class SingletonBase : public QObject
{
      Q_OBJECT
      QML_ELEMENT
      // Not a singleton!
      Q_PROPERTY(QStringList internalFontFamilies READ 
internalFontFamilies CONSTANT FINAL)
public:
     QStringList internalFontFamilies() {
         // The enclosing object does not have to be a singleton
         // in order to return singular data from some getter!
         return QFontDatabase::families()
     }
};

I feel we're touching on a common misconception that many people 
struggle with. Just because some data is conceptually static, you don't 
need to nail it down to a single static QObject. You can just return the 
static data from some method. Each QML engine you expose a single static 
QObject to will try to create its own QObject wrapper. Since we can only 
store one QObject wrapper in the pointer exposed by QObjectPrivate, this 
leads to a hilarious amount of complexity on the side of the QML 
engines. It is also a giant foot gun waiting to trigger when you create 
more than one thread. Yes, it is possible to manage all of this, but 
just don't do it. Let each engine each have its own singleton object and 
dispatch the data in the C++ code you have to write anyway.

By the way, there is also Qt.fontFamilies(). If that is all you need, 
you don't need a special C++ backing type for your singleton at all.

best regards,
Ulf


More information about the Interest mailing list