QGlobalStatic: fix atomics in ~Holder

Back when we set the guard and _then_ destroyed the object, the
atomic_thread_fence was correctly placed between the guard setting and
the dtor invocation.

We know nothing about the payload type. For all we know it could be
some fancy lockless data structure. So in general we need the acquire
fence to synchronize the reads done by the dtor with stores performed
to the object in other threads. The acquire fence did that for us.

But when we reversed the two operations, the fence has moved to after
the dtor call, leaving the dtor unprotected. Move it back to before
the dtor call.

That leaves the store to the guard unordered w.r.t. the execution of
the destructor. To fix, make it a store-release instead.

Amends e3e2674100b1ecbad7117f15c7aa13a704a7d34e.

Pick-to: 6.6 6.5
Change-Id: Ic7adbe17c8b474e82af4e84950c0109984b495d1
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit b6537a9513d274866da2f46827f54e6004196097)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2024-01-23 16:44:23 +01:00 committed by Qt Cherry-pick Bot
parent 3576e60992
commit a57f89251c

View File

@ -40,9 +40,10 @@ template <typename QGS> union Holder
~Holder()
{
// import changes to *pointer() by other threads before running ~PlainType():
std::atomic_thread_fence(std::memory_order_acquire);
pointer()->~PlainType();
std::atomic_thread_fence(std::memory_order_acquire); // avoid mixing stores to guard and *pointer()
guard.storeRelaxed(QtGlobalStatic::Destroyed);
guard.storeRelease(QtGlobalStatic::Destroyed);
}
PlainType *pointer() noexcept