diff options
| author | Thiago Macieira <thiago.macieira@intel.com> | 2012-06-04 22:31:26 +0200 |
|---|---|---|
| committer | Lars Knoll <lars.knoll@qt.io> | 2019-12-07 14:18:19 +0100 |
| commit | f6a151024b03158bcf46dc86e346d4227f8ca9d4 (patch) | |
| tree | 898bbc0be052034801a5269bdd291de09766bd95 /src/corelib/tools/qarraydata.cpp | |
| parent | 8fb45ae5b8b8ad276aeb9bc9e40f351f47523087 (diff) | |
Introduce flags to indicate the QArrayData type
These flags allow us to determine what type of data QArrayData is
carrying. There are currently only two supported types:
- raw data type: constructed via fromRawData or static data
- allocated data type: regular data done via heap allocation
The QArrayData object is usually allocated on the heap, unless its own
reference count is -1 (indicating static const QArrayData). Such
object should have a type of RawDataType, since we can't call free().
Add GrowsBackward for completeness as well as the StaticDataFlags
default for static data.
Change-Id: Icc915a468a2acf2eae91a94e82451f852d382c92
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/corelib/tools/qarraydata.cpp')
| -rw-r--r-- | src/corelib/tools/qarraydata.cpp | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index ce6f1384977..bc486193492 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -153,17 +153,17 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") const QArrayData QArrayData::shared_null[2] = { - { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared null + { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared null /* zero initialized terminator */}; -static const QArrayData qt_array[3] = { - { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared empty - { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, sizeof(QArrayData) }, // unsharable empty +static const QArrayData emptyNotNullShared[2] = { + { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared empty /* zero initialized terminator */}; QT_WARNING_POP -static const QArrayData &qt_array_empty = qt_array[0]; +static const QArrayData &qt_array_empty = emptyNotNullShared[0]; + static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize, uint options) { @@ -179,6 +179,17 @@ static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, siz } } +static QArrayData *allocateData(size_t allocSize, uint options) +{ + QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); + if (header) { + header->ref.atomic.storeRelaxed(1); + header->flags = options; + header->size = 0; + } + return header; +} + static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options) { header = static_cast<QArrayData *>(::realloc(header, allocSize)); @@ -194,38 +205,43 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, Q_ASSERT(alignment >= alignof(QArrayData) && !(alignment & (alignment - 1))); - // Don't allocate empty headers - if (!(options & RawData) && !capacity) + if (capacity == 0) + // optimization for empty headers return const_cast<QArrayData *>(&qt_array_empty); size_t headerSize = sizeof(QArrayData); - // Allocate extra (alignment - alignof(QArrayData)) padding bytes so we - // can properly align the data array. This assumes malloc is able to - // provide appropriate alignment for the header -- as it should! - // Padding is skipped when allocating a header for RawData. - if (!(options & RawData)) - headerSize += (alignment - alignof(QArrayData)); + if (alignment > alignof(QArrayData)) { + // Allocate extra (alignment - Q_ALIGNOF(QArrayData)) padding bytes so we + // can properly align the data array. This assumes malloc is able to + // provide appropriate alignment for the header -- as it should! + headerSize += alignment - alignof(QArrayData); + } if (headerSize > size_t(MaxAllocSize)) return nullptr; size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); - QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); + options |= ArrayOption(AllocatedDataType); + QArrayData *header = allocateData(allocSize, options); if (header) { quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) & ~(alignment - 1); - - header->ref.atomic.storeRelaxed(1); - header->size = 0; - header->alloc = capacity; - header->flags = options; header->offset = data - quintptr(header); + header->alloc = capacity; } return header; } +QArrayData *QArrayData::prepareRawData(ArrayOptions options) Q_DECL_NOTHROW +{ + QArrayData *header = allocateData(sizeof(QArrayData), (options & ~DataTypeBits) | RawDataType); + if (header) + header->alloc = 0; + return header; +} + QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity, ArrayOptions options) noexcept { @@ -233,9 +249,10 @@ QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, Q_ASSERT(data->isMutable()); Q_ASSERT(!data->ref.isShared()); + options |= ArrayOption(AllocatedDataType); size_t headerSize = sizeof(QArrayData); size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); - QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options)); + QArrayData *header = reallocateData(data, allocSize, options); if (header) header->alloc = capacity; return header; |
