Reusing Qt's QString COW / ref counting in a string registry

545 views Asked by At

I work on a project that is supposed to have large object count (in the range of millions), and even though object names are not mandatory, they are supported for the user convenience. It would be quite a big overhead to have an empty string member or even a string pointer for every object considering that named objects will be few and far in between. Also it just so happens that object names are very frequently reused.

So my solution was to create a name registry, basically a QHash<Object*, QString*> which tracks every object that has a name assigned to it, and another string registry, which is a QHash<QString, uint> which tracks the usage count for every string. When objects are named, they are registered in the name registry, when the name is changed or the object is deleted they are unregistered, and the name registry itself manages the string registry, creates the strings, tracks the usage count and if necessary removes entries that are no longer used.

I feel like the second registry may be redundant, since Qt already employs reference counting for its COW scheme, so I wonder how can I employ that already existing functionality to eliminate the string registry and manage the strings usage count and lifetime more elegantly?

1

There are 1 answers

0
Alexander V On

user3735658, for some reason I tend to believe that hash table does not carry the original key string in it, only the hash. So maybe your concern of redundant QString object is not valid (?). It is a bit of question, though... Theoretically, there should not be actual string there. So, you can probably set the key to just anything not valid in the context of your app e.g. "UnnamedObj666" in case of object not tied to the string but still be able to find it via the hash-table /this is where it gets tricky, maybe not, because of inability to resolve collisions by matching with original/.

And, I maybe not replying exactly as you asked but it may work as well, how about

QHash<QString, QSharedDataPointer<YourType1>> collection1;
QHash<QString, QSharedDataPointer<YourType2>> collection2; 
QHash<QString, QSharedDataPointer<YourType3>> collection3;

or maybe just one

QHash<QString, QSharedDataPointer<YourBasicType>> collection;

Using QSharedDataPointer here appears to be the solution as long as you derive YourType from QSharedData to carry the reference counter immediately with the object. This way we have the proper tracking system for all the "floating" references used pretty much anywhere in the program. Of course you create the instance just once and then provide a const ref to QSharedDataPointer to consumer of your object.

There is one problem with the solution above though, when the last named object destructed we still have the entry in the hash table but we can reuse it if so.