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