summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2012-06-11 21:26:23 +0200
committerLars Knoll <lars.knoll@qt.io>2019-12-08 10:29:17 +0100
commit812a611dc05e5facd036856625ccb9274fdcb117 (patch)
tree06151f35165e3b2ae614d21be65e4555e19f45e7 /src/corelib
parent62c673ccc6f81cee09a25f5acceec2768cea4672 (diff)
Stop using the reference counter to store data state
Instead of using the reference count to store whether the data is sharable and whether the header is immutable, move the settings to the flags member. This allows us to save one comparison per deref() or needsDetach(). It also allows for the possibility of mutable data pointed to by a static header. Change-Id: Ie678a2ff2bb9bce73497cb6138b431c465b0f3bb Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/text/qstring.cpp2
-rw-r--r--src/corelib/text/qstringliteral.h2
-rw-r--r--src/corelib/tools/qarraydata.cpp13
-rw-r--r--src/corelib/tools/qarraydata.h27
-rw-r--r--src/corelib/tools/qarraydataops.h4
-rw-r--r--src/corelib/tools/qvector.h2
6 files changed, 29 insertions, 21 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 3e9deba29a..4d3f2016ac 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -2677,7 +2677,7 @@ QString &QString::append(const QString &str)
QString &QString::append(const QChar *str, int len)
{
if (str && len > 0) {
- if (d->isShared() || uint(d->size + len) + 1u > d->allocatedCapacity())
+ if (d->needsDetach() || 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;
diff --git a/src/corelib/text/qstringliteral.h b/src/corelib/text/qstringliteral.h
index 7b4d2d04f5..a0d4ddc30b 100644
--- a/src/corelib/text/qstringliteral.h
+++ b/src/corelib/text/qstringliteral.h
@@ -75,7 +75,7 @@ Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
/**/
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, size, 0, offset } \
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, size, 0, offset } \
/**/
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index fdd441c7de..aa7fac15ef 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -153,11 +153,11 @@ QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
const QArrayData QArrayData::shared_null[2] = {
- { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared null
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared null
/* zero initialized terminator */};
static const QArrayData emptyNotNullShared[2] = {
- { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared empty
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, 0, 0, sizeof(QArrayData) }, // shared empty
/* zero initialized terminator */};
QT_WARNING_POP
@@ -183,7 +183,7 @@ static QArrayData *allocateData(size_t allocSize, uint options)
{
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
if (header) {
- header->ref_.atomic.storeRelaxed(1);
+ header->ref_.storeRelaxed(1);
header->flags = options;
header->size = 0;
}
@@ -222,7 +222,8 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
return nullptr;
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- options |= AllocatedDataType | Mutable;
+ options |= AllocatedDataType | MutableData;
+ options &= ~ImmutableHeader;
QArrayData *header = allocateData(allocSize, options);
if (header) {
quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
@@ -249,10 +250,10 @@ QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize,
Q_ASSERT(data->isMutable());
Q_ASSERT(!data->isShared());
- options |= ArrayOption(AllocatedDataType);
size_t headerSize = sizeof(QArrayData);
size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
- options |= AllocatedDataType | Mutable;
+ options |= AllocatedDataType | MutableData;
+ options &= ~ImmutableHeader;
QArrayData *header = reallocateData(data, allocSize, options);
if (header)
header->alloc = capacity;
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 183cf9f002..56d61340f0 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -56,18 +56,19 @@ struct Q_CORE_EXPORT QArrayData
CapacityReserved = 0x0010, //!< the capacity was reserved by the user, try to keep it
GrowsForward = 0x0020, //!< allocate with eyes towards growing through append()
GrowsBackwards = 0x0040, //!< allocate with eyes towards growing through prepend()
- Mutable = 0x0080, //!< the data can be changed; doesn't say anything about the header
+ MutableData = 0x0080, //!< the data can be changed; doesn't say anything about the header
+ ImmutableHeader = 0x0100, //!< the header is static, it can't be changed
/// this option is used by the Q_ARRAY_LITERAL and similar macros
- StaticDataFlags = RawDataType,
+ StaticDataFlags = RawDataType | ImmutableHeader,
/// this option is used by the allocate() function
- DefaultAllocationFlags = 0,
+ DefaultAllocationFlags = MutableData,
/// this option is used by the prepareRawData() function
DefaultRawFlags = 0
};
Q_DECLARE_FLAGS(ArrayOptions, ArrayOption)
- QtPrivate::RefCount ref_;
+ QBasicAtomicInt ref_;
uint flags;
int size;
uint alloc;
@@ -84,13 +85,19 @@ struct Q_CORE_EXPORT QArrayData
return alloc;
}
+ /// Returns true if sharing took place
bool ref()
{
- return ref_.ref();
+ if (!isStatic())
+ ref_.ref();
+ return true;
}
+ /// Returns false if deallocation is necessary
bool deref()
{
+ if (isStatic())
+ return true;
return ref_.deref();
}
@@ -113,17 +120,17 @@ struct Q_CORE_EXPORT QArrayData
// follow COW principles.
bool isMutable() const
{
- return flags & Mutable;
+ return flags & MutableData;
}
bool isStatic() const
{
- return ref_.isStatic();
+ return flags & ImmutableHeader;
}
bool isShared() const
{
- return ref_.isShared();
+ return ref_.loadRelaxed() != 1;
}
// Returns true if a detach is necessary before modifying the data
@@ -131,7 +138,7 @@ struct Q_CORE_EXPORT QArrayData
// detaching is necessary, you should be in a non-const function already
bool needsDetach()
{
- // ### optimize me -- this currently requires 3 conditionals!
+ // requires two conditionals
return !isMutable() || isShared();
}
@@ -354,7 +361,7 @@ struct QArrayDataPointerRef
};
#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- { Q_REFCOUNT_INITIALIZE_STATIC, QArrayData::StaticDataFlags, size, 0, offset } \
+ { Q_BASIC_ATOMIC_INITIALIZER(-1), QArrayData::StaticDataFlags, size, 0, offset } \
/**/
#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER(type, size) \
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 777f0d839f..11494a5f6f 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -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_.loadRelaxed() == 0);
// As this is to be called only from destructor, it doesn't need to be
// exception safe; size not updated.
@@ -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_.loadRelaxed() == 0);
const T *const b = this->begin();
const T *i = this->end();
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index d9512ee90e..bf422e72d4 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -701,7 +701,7 @@ void QVector<T>::removeLast()
Q_ASSERT(!isEmpty());
Q_ASSERT(d->allocatedCapacity());
- if (d->isShared())
+ if (d->needsDetach())
detach();
--d->size;
if (QTypeInfo<T>::isComplex)