[Development] Qt 5 types under consideration for deprecation / removal in Qt 6

d3fault d3faultdotxbe at gmail.com
Thu May 30 10:12:12 CEST 2019


On 5/29/19, Mutz, Marc via Development <development at qt-project.org> wrote:
> == QSharedDataPointer / QExplicitlySharedDataPointer ==
>
> These are basically Qt-internals, and should never have been public in
> the first place.
>

I disagree (unless there's some replacement you forgot to mention?).
Being able to create implicitly shared classes is extremely useful. I
consider implicit sharing and signals/slots, together, to to be one of
Qt's greatest strengths. They allow you to thread safely access/read a
"single" object across multiple threads without even thinking about
threading primitives such as mutex/waitcondition. You can also thread
safely modify/write to that object, by copying/detach()'ing just
before write (CoW).

I think the reason QSharedDataPointer hasn't seen very much use in
user code is because it's so darn tedious and time consuming to setup.
There's a lot of boilerplate/repetitive code in the EmployeeData
example of QSharedDataPointer's doc. At least that's why I
rarely/never use it in my own code. But there's a solution to that,
outlined here: https://bugreports.qt.io/browse/QTBUG-68589 (the
"Sample.isd"/json design in the comments of that bug report would be
very easy to implement).


> == QLinkedList -> std::list
> == QQueue / QStack -> std::queue, std::stack ==
> == QSet / QHash -> std::unordered_set/map ==
> == QMap -> std::map ==
>

Disagree. The software design process differs too greatly when dealing
with CoW vs. non-CoW containers. Assuming you could do s/QMap/std::map
(etc for all the containers) and have it compile without changing
anything else, there are just fundamental differences in the way
you're expected to use the containers. With Qt's CoW containers you
refer to a container by value, even from multiple threads
*simultaneously*, and it never performs a deep copy unless you try to
modify the container. ex:

Thread #0:
    emit fooSignal(someQMap);

Thread #1:
void someFooSlot(someQMap)
{
    m_MyCopy = someQMap; //with a CoW container the atomic reference
count is just incremented by 1. with a non-CoW container a deep copy
is performed here
}

Tons of user code was designed relying on there being CoW containers,
so removing it would make memory consumption skyrocket (OOM likely). I
don't see this as a feasible change. Hypothetically, how would one
thread safely share a std container with another thread (via
signals/slots) without performing a deep copy? Pass a
reference/pointer to the container and pass mutex along with it? That
would require lots of code changes (mutex.lock everywhere) and would
be prone to use-after-free errors (Qt's CoW semantics do lifetime
management seamlessly).

I recommend doing what someone else suggested in this thread: keep the
Qt'ish API (enqueue/dequeue vs. push/pop etc) and use the std
containers for the underlying implementation (just wrapped in CoW).


d3fault


More information about the Development mailing list