QPainter: make Private::d_ptrs a QVLA<unique_ptr>

This way, we remove the impedance mismatch between QPainter::d_ptr
(which already is a unique_ptr) and Private::d_ptrs, which still dealt
in raw pointers, simplifying the code.

Since we're now owning the objects in d_ptrs, add an assertion that
d_ptrs is empty on QPainter destruction.

Coverity-Id: 425479
Change-Id: I849e80752b4bc5a71aef8d47663c6ffc9fdca9f7
Reviewed-by: Matthias Rauter <matthias.rauter@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Marc Mutz 2025-05-20 20:38:38 +02:00
parent e670a6d77b
commit 3e98657898
2 changed files with 6 additions and 9 deletions

View File

@ -247,11 +247,7 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
// the current d_ptr to the shared painter's d_ptr.
sp->save();
++sp->d_ptr->refcount;
{
// ensure realloc happens before the unique_ptr::release():
auto &p = sp->d_ptr->d_ptrs.emplace_back();
p = q->d_ptr.release();
}
sp->d_ptr->d_ptrs.push_back(std::move(q->d_ptr));
q->d_ptr.reset(sp->d_ptr.get());
Q_ASSERT(q->d_ptr->state);
@ -296,19 +292,19 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
Q_ASSERT(q);
--refcount;
QPainterPrivate *original = d_ptrs.back();
auto original = std::move(d_ptrs.back());
d_ptrs.pop_back();
if (inDestructor) {
inDestructor = false;
if (original)
original->inDestructor = true;
} else if (!original) {
original = new QPainterPrivate(q);
original = std::make_unique<QPainterPrivate>(q);
}
q->restore();
Q_UNUSED(q->d_ptr.release());
q->d_ptr.reset(original);
q->d_ptr = std::move(original);
if (emulationEngine) {
extended = emulationEngine->real_engine;
@ -1488,6 +1484,7 @@ QPainter::~QPainter()
Q_ASSERT(d_ptr->inDestructor);
d_ptr->inDestructor = false;
Q_ASSERT(d_ptr->refcount == 1);
Q_ASSERT(d_ptr->d_ptrs.empty());
}
}

View File

@ -166,7 +166,7 @@ public:
// redirections within the same paintEvent(), which should be enough
// in 99% of all cases). E.g: A renders B which renders C which renders D.
static constexpr qsizetype NDPtrs = 4;
QVarLengthArray<QPainterPrivate*, NDPtrs> d_ptrs;
QVarLengthArray<std::unique_ptr<QPainterPrivate>, NDPtrs> d_ptrs;
std::unique_ptr<QPainterState> state;
template <typename T, std::size_t N = 8>