From 62c673ccc6f81cee09a25f5acceec2768cea4672 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 11 Jun 2012 19:42:05 +0200 Subject: Add reference-count manipulation functions to QArrayData and hide ref The next change will stop using some values in the reference counter as settings from the data. Change-Id: I94df1fe643896373fac2f000fff55bc7708fc807 Reviewed-by: Simon Hausmann --- src/corelib/kernel/qmetaobject.cpp | 2 +- src/corelib/serialization/qbinaryjsonvalue.cpp | 8 ++++---- src/corelib/text/qbytearray.cpp | 22 +++++++++++----------- src/corelib/text/qbytearray.h | 8 ++++---- src/corelib/text/qstring.cpp | 14 +++++++------- src/corelib/text/qstring.h | 8 ++++---- src/corelib/text/qstringliteral.h | 2 +- src/corelib/tools/qarraydata.cpp | 6 +++--- src/corelib/tools/qarraydata.h | 26 +++++++++++++++++++++++--- src/corelib/tools/qarraydataops.h | 26 +++++++++++++------------- src/corelib/tools/qarraydatapointer.h | 4 ++-- src/corelib/tools/qvector.h | 20 ++++++++++---------- 12 files changed, 83 insertions(+), 63 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index d9feb76d04..f093111a8c 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -158,7 +158,7 @@ static inline const QByteArray stringData(const QMetaObject *mo, int index) { Q_ASSERT(priv(mo->d.data)->revision >= 7); const QByteArrayDataPtr data = { const_cast(&mo->d.stringdata[index]) }; - Q_ASSERT(data.ptr->ref.isStatic()); + Q_ASSERT(data.ptr->isStatic()); Q_ASSERT(data.ptr->allocatedCapacity() == 0); Q_ASSERT(data.ptr->size >= 0); return data; diff --git a/src/corelib/serialization/qbinaryjsonvalue.cpp b/src/corelib/serialization/qbinaryjsonvalue.cpp index 5e3a01ad38..46a1b80104 100644 --- a/src/corelib/serialization/qbinaryjsonvalue.cpp +++ b/src/corelib/serialization/qbinaryjsonvalue.cpp @@ -66,7 +66,7 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data, case QJsonValue::String: { QString s = v.toString(parent); stringData = s.data_ptr(); - stringData->ref.ref(); + stringData->ref(); break; } case QJsonValue::Array: @@ -82,7 +82,7 @@ QBinaryJsonValue::QBinaryJsonValue(QBinaryJsonPrivate::MutableData *data, QBinaryJsonValue::QBinaryJsonValue(QString string) : stringData(*reinterpret_cast(&string)), t(QJsonValue::String) { - stringData->ref.ref(); + stringData->ref(); } QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonArray &a) @@ -101,7 +101,7 @@ QBinaryJsonValue::QBinaryJsonValue(const QBinaryJsonObject &o) QBinaryJsonValue::~QBinaryJsonValue() { - if (t == QJsonValue::String && stringData && !stringData->ref.deref()) + if (t == QJsonValue::String && stringData && !stringData->deref()) free(stringData); if (d && !d->ref.deref()) @@ -134,7 +134,7 @@ QString QBinaryJsonValue::toString() const { if (t != QJsonValue::String) return QString(); - stringData->ref.ref(); // the constructor below doesn't add a ref. + stringData->ref(); // the constructor below doesn't add a ref. QStringDataPtr holder = { stringData }; return QString(holder); } diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index da91a93700..78395a47e3 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -1184,8 +1184,8 @@ QByteArray qUncompress(const uchar* data, int nbytes) */ QByteArray &QByteArray::operator=(const QByteArray & other) noexcept { - other.d->ref.ref(); - if (!d->ref.deref()) + other.d->ref(); + if (!d->deref()) Data::deallocate(d); d = other.d; return *this; @@ -1215,8 +1215,8 @@ QByteArray &QByteArray::operator=(const char *str) memcpy(x->data(), str, fullLen); // include null terminator x->size = len; } - x->ref.ref(); - if (!d->ref.deref()) + x->ref(); + if (!d->deref()) Data::deallocate(d); d = x; return *this; @@ -1755,12 +1755,12 @@ void QByteArray::resize(int size) if (size < 0) size = 0; - if (!d->ref.isShared() && !d->isMutable() && size < d->size) { + if (!d->isShared() && !d->isMutable() && size < d->size) { d->size = size; return; } - if (d->size == 0 && d->ref.isStatic()) { + if (d->size == 0 && d->isStatic()) { // // Optimize the idiom: // QByteArray a; @@ -1811,7 +1811,7 @@ void QByteArray::reallocData(uint alloc, Data::ArrayOptions options) x->size = qMin(int(alloc) - 1, d->size); ::memcpy(x->data(), d->data(), x->size); x->data()[x->size] = '\0'; - if (!d->ref.deref()) + if (!d->deref()) Data::deallocate(d); d = x; } else { @@ -1869,7 +1869,7 @@ QByteArray QByteArray::nulTerminated() const QByteArray &QByteArray::prepend(const QByteArray &ba) { - if (d->size == 0 && d->ref.isStatic() && !IS_RAW_DATA(ba.d)) { + if (d->size == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) { *this = ba; } else if (ba.d->size != 0) { QByteArray tmp = *this; @@ -1961,7 +1961,7 @@ QByteArray &QByteArray::prepend(char ch) QByteArray &QByteArray::append(const QByteArray &ba) { - if (d->size == 0 && d->ref.isStatic() && !IS_RAW_DATA(ba.d)) { + if (d->size == 0 && d->isStatic() && !IS_RAW_DATA(ba.d)) { *this = ba; } else if (ba.d->size != 0) { if (d->needsDetach() || d->size + ba.d->size > capacity()) @@ -3239,7 +3239,7 @@ QByteArray QByteArray::toUpper_helper(QByteArray &a) void QByteArray::clear() { - if (!d->ref.deref()) + if (!d->deref()) Data::deallocate(d); d = Data::sharedNull(); } @@ -4471,7 +4471,7 @@ QByteArray &QByteArray::setRawData(const char *data, uint size) { if (!data || !size) { clear(); - } else if (d->ref.isShared() || (d->flags & Data::RawDataType) == 0) { + } else if (d->isShared() || (d->flags & Data::RawDataType) == 0) { *this = fromRawData(data, size); } else { d->size = size; diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h index 597bc8bcb3..e9e4eecd26 100644 --- a/src/corelib/text/qbytearray.h +++ b/src/corelib/text/qbytearray.h @@ -123,7 +123,7 @@ template struct QStaticByteArrayData QByteArrayData *data_ptr() const { - Q_ASSERT(ba.ref.isStatic()); + Q_ASSERT(ba.isStatic()); return const_cast(&ba); } }; @@ -469,7 +469,7 @@ public: Q_DECLARE_OPERATORS_FOR_FLAGS(QByteArray::Base64Options) inline QByteArray::QByteArray() noexcept : d(Data::sharedNull()) { } -inline QByteArray::~QByteArray() { if (!d->ref.deref()) Data::deallocate(d); } +inline QByteArray::~QByteArray() { if (!d->deref()) Data::deallocate(d); } inline int QByteArray::size() const { return d->size; } @@ -497,9 +497,9 @@ inline const char *QByteArray::constData() const inline void QByteArray::detach() { if (d->needsDetach()) reallocData(uint(d->size) + 1u, d->detachFlags()); } inline bool QByteArray::isDetached() const -{ return !d->ref.isShared(); } +{ return !d->isShared(); } inline QByteArray::QByteArray(const QByteArray &a) noexcept : d(a.d) -{ d->ref.ref(); } +{ d->ref(); } inline int QByteArray::capacity() const { int realCapacity = d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; } diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index ab08d497bd..3e9deba29a 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -2265,7 +2265,7 @@ void QString::resize(int size) if (size < 0) size = 0; - if (!d->ref.isShared() && !d->isMutable() && size < d->size) { + if (!d->isShared() && !d->isMutable() && size < d->size) { d->size = size; return; } @@ -2359,7 +2359,7 @@ void QString::reallocData(uint alloc, bool grow) x->size = qMin(int(alloc) - 1, d->size); ::memcpy(x->data(), d->data(), x->size * sizeof(QChar)); x->data()[x->size] = 0; - if (!d->ref.deref()) + if (!d->deref()) Data::deallocate(d); d = x; } else { @@ -2391,8 +2391,8 @@ void QString::expand(int i) QString &QString::operator=(const QString &other) noexcept { - other.d->ref.ref(); - if (!d->ref.deref()) + other.d->ref(); + if (!d->deref()) Data::deallocate(d); d = other.d; return *this; @@ -2677,7 +2677,7 @@ QString &QString::append(const QString &str) QString &QString::append(const QChar *str, int len) { if (str && len > 0) { - if (d->ref.isShared() || uint(d->size + len) + 1u > d->allocatedCapacity()) + if (d->isShared() || uint(d->size + len) + 1u > d->allocatedCapacity()) reallocData(uint(d->size + len) + 1u, true); memcpy(d->data() + d->size, str, len * sizeof(QChar)); d->size += len; @@ -5372,7 +5372,7 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size) QString::Data *QString::fromAscii_helper(const char *str, int size) { QString s = fromUtf8(str, size); - s.d->ref.ref(); + s.d->ref(); return s.d; } @@ -9151,7 +9151,7 @@ QString &QString::setRawData(const QChar *unicode, int size) { if (!unicode || !size) { clear(); - } else if (d->ref.isShared() || !IS_RAW_DATA(d)) { + } else if (d->isShared() || !IS_RAW_DATA(d)) { *this = fromRawData(unicode, size); } else { d->size = size; diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index fd674284fe..bcc1200125 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2019 Intel Corporation. ** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** @@ -1043,11 +1043,11 @@ inline const QChar *QString::constData() const inline void QString::detach() { if (d->needsDetach()) reallocData(uint(d->size) + 1u); } inline bool QString::isDetached() const -{ return !d->ref.isShared(); } +{ return !d->isShared(); } inline void QString::clear() { if (!isNull()) *this = QString(); } inline QString::QString(const QString &other) noexcept : d(other.d) -{ Q_ASSERT(&other != this); d->ref.ref(); } +{ Q_ASSERT(&other != this); d->ref(); } inline int QString::capacity() const { int realCapacity = d->constAllocatedCapacity(); return realCapacity ? realCapacity - 1 : 0; } inline QString &QString::setNum(short n, int base) @@ -1259,7 +1259,7 @@ inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); } inline QString::QString() noexcept : d(Data::sharedNull()) {} -inline QString::~QString() { if (!d->ref.deref()) Data::deallocate(d); } +inline QString::~QString() { if (!d->deref()) Data::deallocate(d); } inline void QString::reserve(int asize) { diff --git a/src/corelib/text/qstringliteral.h b/src/corelib/text/qstringliteral.h index 796909dcab..7b4d2d04f5 100644 --- a/src/corelib/text/qstringliteral.h +++ b/src/corelib/text/qstringliteral.h @@ -94,7 +94,7 @@ struct QStaticStringData QStringData *data_ptr() const { - Q_ASSERT(str.ref.isStatic()); + Q_ASSERT(str.isStatic()); return const_cast(static_cast(&str)); } }; diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 3123d7467f..fdd441c7de 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -183,7 +183,7 @@ static QArrayData *allocateData(size_t allocSize, uint options) { QArrayData *header = static_cast(::malloc(allocSize)); if (header) { - header->ref.atomic.storeRelaxed(1); + header->ref_.atomic.storeRelaxed(1); header->flags = options; header->size = 0; } @@ -247,7 +247,7 @@ QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, { Q_ASSERT(data); Q_ASSERT(data->isMutable()); - Q_ASSERT(!data->ref.isShared()); + Q_ASSERT(!data->isShared()); options |= ArrayOption(AllocatedDataType); size_t headerSize = sizeof(QArrayData); @@ -267,7 +267,7 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize, && !(alignment & (alignment - 1))); Q_UNUSED(objectSize) Q_UNUSED(alignment) - Q_ASSERT_X(data == 0 || !data->ref.isStatic(), "QArrayData::deallocate", + Q_ASSERT_X(data == 0 || !data->isStatic(), "QArrayData::deallocate", "Static data cannot be deleted"); ::free(data); } diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index 8c21fd55c8..183cf9f002 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -67,7 +67,7 @@ struct Q_CORE_EXPORT QArrayData }; Q_DECLARE_FLAGS(ArrayOptions, ArrayOption) - QtPrivate::RefCount ref; + QtPrivate::RefCount ref_; uint flags; int size; uint alloc; @@ -84,6 +84,16 @@ struct Q_CORE_EXPORT QArrayData return alloc; } + bool ref() + { + return ref_.ref(); + } + + bool deref() + { + return ref_.deref(); + } + void *data() { Q_ASSERT(size == 0 @@ -106,13 +116,23 @@ struct Q_CORE_EXPORT QArrayData return flags & Mutable; } + bool isStatic() const + { + return ref_.isStatic(); + } + + bool isShared() const + { + return ref_.isShared(); + } + // Returns true if a detach is necessary before modifying the data // This method is intentionally not const: if you want to know whether // detaching is necessary, you should be in a non-const function already bool needsDetach() { // ### optimize me -- this currently requires 3 conditionals! - return !isMutable() || ref.isShared(); + return !isMutable() || isShared(); } size_t detachCapacity(size_t newSize) const @@ -290,7 +310,7 @@ struct QTypedArrayData Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData)); QTypedArrayData *result = static_cast(prepareRawData(options)); if (result) { - Q_ASSERT(!result->ref.isShared()); // No shared empty, please! + Q_ASSERT(!result->isShared()); // No shared empty, please! result->offset = reinterpret_cast(data) - reinterpret_cast(result); diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h index 7724049be8..777f0d839f 100644 --- a/src/corelib/tools/qarraydataops.h +++ b/src/corelib/tools/qarraydataops.h @@ -61,7 +61,7 @@ struct QPodArrayOps void appendInitialize(size_t newSize) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(newSize > uint(this->size)); Q_ASSERT(newSize <= this->allocatedCapacity()); @@ -72,7 +72,7 @@ struct QPodArrayOps void copyAppend(const T *b, const T *e) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(b < e); Q_ASSERT(e - b <= this->allocatedCapacity() - this->size); @@ -84,7 +84,7 @@ struct QPodArrayOps void copyAppend(size_t n, const T &t) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(n <= uint(this->allocatedCapacity() - this->size)); T *iter = this->end(); @@ -97,7 +97,7 @@ struct QPodArrayOps void truncate(size_t newSize) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(newSize < size_t(this->size)); this->size = int(newSize); @@ -106,7 +106,7 @@ struct QPodArrayOps void destroyAll() // Call from destructors, ONLY! { Q_ASSERT(this->isMutable()); - Q_ASSERT(this->ref.atomic.loadRelaxed() == 0); + Q_ASSERT(this->ref_.atomic.loadRelaxed() == 0); // As this is to be called only from destructor, it doesn't need to be // exception safe; size not updated. @@ -115,7 +115,7 @@ struct QPodArrayOps void insert(T *where, const T *b, const T *e) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap @@ -148,7 +148,7 @@ struct QGenericArrayOps void appendInitialize(size_t newSize) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(newSize > uint(this->size)); Q_ASSERT(newSize <= this->allocatedCapacity()); @@ -161,7 +161,7 @@ struct QGenericArrayOps void copyAppend(const T *b, const T *e) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(b < e); Q_ASSERT(e - b <= this->allocatedCapacity() - this->size); @@ -175,7 +175,7 @@ struct QGenericArrayOps void copyAppend(size_t n, const T &t) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(n <= size_t(this->allocatedCapacity() - this->size)); T *iter = this->end(); @@ -189,7 +189,7 @@ struct QGenericArrayOps void truncate(size_t newSize) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(newSize < size_t(this->size)); const T *const b = this->begin(); @@ -204,7 +204,7 @@ struct QGenericArrayOps // As this is to be called only from destructor, it doesn't need to be // exception safe; size not updated. - Q_ASSERT(this->ref.atomic.loadRelaxed() == 0); + Q_ASSERT(this->ref_.atomic.loadRelaxed() == 0); const T *const b = this->begin(); const T *i = this->end(); @@ -216,7 +216,7 @@ struct QGenericArrayOps void insert(T *where, const T *b, const T *e) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap @@ -312,7 +312,7 @@ struct QMovableArrayOps void insert(T *where, const T *b, const T *e) { Q_ASSERT(this->isMutable()); - Q_ASSERT(!this->ref.isShared()); + Q_ASSERT(!this->isShared()); Q_ASSERT(where >= this->begin() && where < this->end()); // Use copyAppend at end Q_ASSERT(b < e); Q_ASSERT(e <= where || b > this->end()); // No overlap diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h index b7236d485a..86997985d1 100644 --- a/src/corelib/tools/qarraydatapointer.h +++ b/src/corelib/tools/qarraydatapointer.h @@ -58,7 +58,7 @@ public: } QArrayDataPointer(const QArrayDataPointer &other) - : d(other.d->ref.ref() + : d(other.d->ref() ? other.d : other.clone(other.d->cloneFlags())) { @@ -109,7 +109,7 @@ public: ~QArrayDataPointer() { - if (!d->ref.deref()) { + if (!d->deref()) { if (d->isMutable()) (*this)->destroyAll(); Data::deallocate(d); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index a596beedcf..d9512ee90e 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -89,7 +89,7 @@ public: explicit QVector(int size); QVector(int size, const T &t); inline QVector(const QVector &v); - inline ~QVector() { if (!d->ref.deref()) freeData(d); } + inline ~QVector() { if (!d->deref()) freeData(d); } QVector &operator=(const QVector &v); QVector(QVector &&other) noexcept : d(other.d) { other.d = Data::sharedNull(); } QVector &operator=(QVector &&other) noexcept @@ -114,17 +114,17 @@ public: void reserve(int size); inline void squeeze() { - if (d->size < int(d->alloc)) { + if (d->size < int(d->allocatedCapacity())) { if (!d->size) { *this = QVector(); return; } - realloc(d->size, QArrayData::ArrayOptions(d->flags)); + realloc(d->size, d->detachFlags()); } } inline void detach(); - inline bool isDetached() const { return !d->ref.isShared(); } + inline bool isDetached() const { return !d->isShared(); } inline bool isSharedWith(const QVector &other) const { return d == other.d; } @@ -365,7 +365,7 @@ void QVector::destruct(T *from, T *to) template inline QVector::QVector(const QVector &v) { - if (v.d->ref.ref()) { + if (v.d->ref()) { d = v.d; } else { if (v.d->flags & Data::CapacityReserved) { @@ -391,7 +391,7 @@ template void QVector::detach() { // ### check whether this is still required - if (d->ref.isStatic()) + if (d->isStatic()) return; if (d->needsDetach()) @@ -581,14 +581,14 @@ void QVector::realloc(int aalloc, QArrayData::ArrayOptions options) Q_ASSERT(aalloc >= d->size); Data *x = d; - const bool isShared = d->ref.isShared(); + const bool isShared = d->isShared(); QT_TRY { // allocate memory x = Data::allocate(aalloc, options); Q_CHECK_PTR(x); // aalloc is bigger then 0 so it is not [un]sharedEmpty - Q_ASSERT(!x->ref.isStatic()); + Q_ASSERT(!x->isStatic()); x->size = d->size; T *srcBegin = d->begin(); @@ -621,7 +621,7 @@ void QVector::realloc(int aalloc, QArrayData::ArrayOptions options) } Q_ASSERT(d != x); - if (!d->ref.deref()) { + if (!d->deref()) { if (!QTypeInfoQuery::isRelocatable || !aalloc || (isShared && QTypeInfo::isComplex)) { // data was copy constructed, we need to call destructors // or if !alloc we did nothing to the old 'd'. @@ -701,7 +701,7 @@ void QVector::removeLast() Q_ASSERT(!isEmpty()); Q_ASSERT(d->allocatedCapacity()); - if (d->ref.isShared()) + if (d->isShared()) detach(); --d->size; if (QTypeInfo::isComplex) -- cgit v1.2.3