diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-07-10 14:06:36 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-08-24 00:17:04 +0200 |
commit | 6754198c338abd560f3af31ff09630e0f1085843 (patch) | |
tree | 4354bf6840007f90c6187adc5e0a33e39f2fdcf3 /src/corelib/kernel/qvariant.h | |
parent | 76e8e8e9c8093f093cb9f37d61d273f43398fefb (diff) |
Cleanup QVariant::PrivateShared
Remove the additional indirection through ptr and replace
it with an offset calculation. Get rid of PrivateSharedEx
that was handling certain types differently.
This also fixes the support for overaligned types, by
using the alignment field from QMetaType to determine
the alignment requirements.
Change-Id: Icc6a78eb57f664c7747450578fe58dfee8f2863b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r-- | src/corelib/kernel/qvariant.h | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index b738b80d38..96756fdda7 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -52,7 +52,6 @@ #ifndef QT_BOOTSTRAPPED #include <QtCore/qbytearraylist.h> #endif - #include <memory> #if __has_include(<variant>) && __cplusplus >= 201703L @@ -405,9 +404,40 @@ class Q_CORE_EXPORT QVariant public: struct PrivateShared { - inline PrivateShared(void *v) : ptr(v), ref(1) { } - void *ptr; - QAtomicInt ref; + private: + inline PrivateShared() : ref(1) { } + public: + static PrivateShared *create(QMetaType type) + { + size_t size = type.sizeOf(); + size_t align = type.alignOf(); + + size += sizeof(PrivateShared); + if (align > sizeof(PrivateShared)) { + // The alignment is larger than the alignment we can guarantee for the pointer + // directly following PrivateShared, so we need to allocate some additional + // memory to be able to fit the object into the available memory with suitable + // alignment. + size += align - sizeof(PrivateShared); + } + void *data = operator new(size); + auto *ps = new (data) QVariant::PrivateShared(); + ps->offset = int(((quintptr(ps) + sizeof(PrivateShared) + align - 1) & ~(align - 1)) - quintptr(ps)); + return ps; + } + static void free(PrivateShared *p) + { + p->~PrivateShared(); + operator delete(p); + } + + alignas(8) QAtomicInt ref; + int offset; + + const void *data() const + { return reinterpret_cast<const unsigned char *>(this) + offset; } + void *data() + { return reinterpret_cast<unsigned char *>(this) + offset; } }; struct Private { |