On 2019-08-07 22:01, Konstantin Tokarev wrote:
It would be even better if it was possible to choose type of reference counting, e.g. via template parameter. In many cases atomic counters are not needed
and just reduce performance.

On 2019-08-07 21:46, Philippe wrote:
On Wed, 07 Aug 2019 21:00:30 +0300
"Mutz, Marc" <m...@kdab.com> wrote:
[...]
I think I'm on record saying such impl details as ref-counting for Qt implicitly shared classes should not be public API. This is a perfect example of why I believe that to be fundamentally true.

+1

I have just uploaded my proposed solution for this: QIntrusiveSharedPointer. Even though I didn't have a) taking Qt pimpl private and b) allowing non-atomic ref counts use-cases in mind when I designed it, it supports these use-cases out of the box. I think its design will satisfy all the constraints, even though I'd like to see a round of internal use first (5.14, or, more likely by now 5.15, make public in Qt 6):

- provide a public replacement for QSharedDataPointer/QExplicitlySharedDataPointer with all their (known) shortcomings fixed

while at the same time:

- allow Qt to use it's own private reference counting (by having qshareddatav2_p.h and the Intrusive Protocol implemented like for QSharedData); I haven't implemented a QSDV2, yet, but off the top of my head the ref-counting is always out-of-line, so it's possible to retrofit it into already-released classes

- allow users to use a simple int as ref-count

This is an evolution of https://codereview.qt-project.org/c/qt/qtbase/+/115213 and it has all the benefits of QtPrivate::SharedDataPointer to, to wit:

- it's possible to have an inline move ctor:

just need to export an out-of-line overload of qIntrusiveDeref(QXXXPrivate*), which can call qIntrusiveDeref<QXXXPrivate>() if Private is derived from a supported QSharedData-alike

- in the same way, even the dtor can be inline
- it's even possible to have all special member functions = default'ed

by exporting qIntrusiveRef() in addition. This reduces the number of DLL entry points from 4 (default, copy ctor/assignment op, dtor) to two (qIntrusive(De)ref()).

- const propagating
- explicit detach
- proper conversion to bool (unlike QSDP, which detaches, making every if (mutable d) tautological)

It also adds

- constexpr default ctor and ctor from nullptr
- implicit ctor from nullptr (but explicit from T*)

Which means that on conforming compilers (not MSVC) a static QISP init'ed to nullptr will be placed into the BSS segment and not cause dynamic initialisation (even if the dtor is not trivial - the std::mutex principle).

The only drawback over QtPrivate::SharedDataPointer is that you need to manually declare and implement qIntrusiveRef() and qIntrusiveDeref(); we can't hide it in (one) macro. But I think that's a benefit. It reduces the number of DLL entry points over the static-Public-member-functions design of QtP::SDP, which is probably the reason it consistently produces less executable code than QSDP, QESDP and not more code than QtP::SDP did (which sometimes, e.g. for QCommandLineArgument, increased text size a bit).

Flame away...

Thanks,
Marc
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to