summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2011-11-22 17:28:14 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-09 17:19:30 +0100
commitf1e48d48fd58b28b1dc18652af3fc74da5e112fd (patch)
tree41f355093999ea8dabf9c196afb4e0ad275ce547
parentd91b4f0b13926a0861d7e172f14437d20d06332e (diff)
Add AllocateOptions to QArrayData
This approach is better for future ABI evolution than using individual bool parameters. QArrayData now also offers to calculate allocate options for typical detach and clone operations: the CapacityReserved flag is preserved, while cloning resets the Unsharable state. Change-Id: I256e135adcf27a52a5c7d6130069c35c8b946bc3 Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
-rw-r--r--src/corelib/tools/qarraydata.cpp8
-rw-r--r--src/corelib/tools/qarraydata.h37
-rw-r--r--src/corelib/tools/qarraydatapointer.h12
-rw-r--r--tests/auto/corelib/tools/qarraydata/simplevector.h12
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp42
5 files changed, 78 insertions, 33 deletions
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 150f23cc12..efed984aef 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -49,7 +49,7 @@ static const QArrayData qt_array_empty = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0
static const QArrayData qt_array_unsharable_empty = { { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, 0 };
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
- size_t capacity, bool reserve, bool sharable)
+ size_t capacity, AllocateOptions options)
{
// Alignment is a power of two
Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)
@@ -57,7 +57,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
// Don't allocate empty headers
if (!capacity)
- return sharable
+ return !(options & Unsharable)
? const_cast<QArrayData *>(&qt_array_empty)
: const_cast<QArrayData *>(&qt_array_unsharable_empty);
@@ -73,10 +73,10 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
& ~(alignment - 1);
- header->ref.atomic.store(sharable ? 1 : 0);
+ header->ref.atomic.store(bool(!(options & Unsharable)));
header->size = 0;
header->alloc = capacity;
- header->capacityReserved = reserve;
+ header->capacityReserved = bool(options & CapacityReserved);
header->offset = data - quintptr(header);
}
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 2486bebafa..8eb543ee51 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -73,14 +73,43 @@ struct Q_CORE_EXPORT QArrayData
return reinterpret_cast<const char *>(this) + offset;
}
+ enum AllocateOption {
+ CapacityReserved = 0x1,
+ Unsharable = 0x2,
+
+ Default = 0
+ };
+
+ Q_DECLARE_FLAGS(AllocateOptions, AllocateOption)
+
+ AllocateOptions detachFlags() const
+ {
+ AllocateOptions result;
+ if (!ref.isSharable())
+ result |= Unsharable;
+ if (capacityReserved)
+ result |= CapacityReserved;
+ return result;
+ }
+
+ AllocateOptions cloneFlags() const
+ {
+ AllocateOptions result;
+ if (capacityReserved)
+ result |= CapacityReserved;
+ return result;
+ }
+
static QArrayData *allocate(size_t objectSize, size_t alignment,
- size_t capacity, bool reserve, bool sharable) Q_REQUIRED_RESULT;
+ size_t capacity, AllocateOptions options = Default) Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
size_t alignment);
static const QArrayData shared_null;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QArrayData::AllocateOptions)
+
template <class T>
struct QTypedArrayData
: QArrayData
@@ -98,11 +127,11 @@ struct QTypedArrayData
class AlignmentDummy { QArrayData header; T data; };
- static QTypedArrayData *allocate(size_t capacity, bool reserve = false,
- bool sharable = true) Q_REQUIRED_RESULT
+ static QTypedArrayData *allocate(size_t capacity,
+ AllocateOptions options = Default) Q_REQUIRED_RESULT
{
return static_cast<QTypedArrayData *>(QArrayData::allocate(sizeof(T),
- Q_ALIGNOF(AlignmentDummy), capacity, reserve, sharable));
+ Q_ALIGNOF(AlignmentDummy), capacity, options));
}
static void deallocate(QArrayData *data)
diff --git a/src/corelib/tools/qarraydatapointer.h b/src/corelib/tools/qarraydatapointer.h
index c03e2ef849..1dc02daa63 100644
--- a/src/corelib/tools/qarraydatapointer.h
+++ b/src/corelib/tools/qarraydatapointer.h
@@ -66,7 +66,7 @@ public:
QArrayDataPointer(const QArrayDataPointer &other)
: d(other.d->ref.ref()
? other.d
- : other.clone())
+ : other.clone(other.d->cloneFlags()))
{
}
@@ -115,7 +115,9 @@ public:
void setSharable(bool sharable)
{
if (d->alloc == 0 && d->size == 0) {
- d = Data::allocate(0, false, sharable);
+ d = Data::allocate(0, sharable
+ ? QArrayData::Default
+ : QArrayData::Unsharable);
return;
}
@@ -137,7 +139,7 @@ public:
bool detach()
{
if (d->ref.isShared()) {
- Data *copy = clone();
+ Data *copy = clone(d->detachFlags());
QArrayDataPointer old(d);
d = copy;
return true;
@@ -147,10 +149,10 @@ public:
}
private:
- Data *clone() const Q_REQUIRED_RESULT
+ Data *clone(QArrayData::AllocateOptions options) const Q_REQUIRED_RESULT
{
QArrayDataPointer copy(Data::allocate(d->alloc ? d->alloc : d->size,
- d->capacityReserved));
+ options));
if (d->size)
copy->copyAppend(d->begin(), d->end());
diff --git a/tests/auto/corelib/tools/qarraydata/simplevector.h b/tests/auto/corelib/tools/qarraydata/simplevector.h
index 9ab28a9ddd..4f02df1c40 100644
--- a/tests/auto/corelib/tools/qarraydata/simplevector.h
+++ b/tests/auto/corelib/tools/qarraydata/simplevector.h
@@ -140,7 +140,8 @@ public:
|| (n
&& !d->capacityReserved
&& (d->ref != 1 || (d->capacityReserved = 1, false)))) {
- SimpleVector detached(Data::allocate(n, true));
+ SimpleVector detached(Data::allocate(n,
+ d->detachFlags() | Data::CapacityReserved));
detached.d->copyAppend(constBegin(), constEnd());
detached.swap(*this);
}
@@ -160,7 +161,8 @@ public:
if (d->ref != 1
|| capacity() - size() < size_t(last - first)) {
SimpleVector detached(Data::allocate(
- qMax(capacity(), size() + (last - first)), d->capacityReserved));
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags()));
detached.d->copyAppend(first, last);
detached.d->copyAppend(begin, begin + d->size);
@@ -180,7 +182,8 @@ public:
if (d->ref != 1
|| capacity() - size() < size_t(last - first)) {
SimpleVector detached(Data::allocate(
- qMax(capacity(), size() + (last - first)), d->capacityReserved));
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags()));
if (d->size) {
const T *const begin = constBegin();
@@ -219,7 +222,8 @@ public:
if (d->ref != 1
|| capacity() - size() < size_t(last - first)) {
SimpleVector detached(Data::allocate(
- qMax(capacity(), size() + (last - first)), d->capacityReserved));
+ qMax(capacity(), size() + (last - first)),
+ d->detachFlags()));
if (position)
detached.d->copyAppend(begin, where);
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index 47d5e2a32b..2df4131f4a 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -153,7 +153,7 @@ void tst_QArrayData::referenceCounting()
void tst_QArrayData::sharedNullEmpty()
{
QArrayData *null = const_cast<QArrayData *>(&QArrayData::shared_null);
- QArrayData *empty = QArrayData::allocate(1, Q_ALIGNOF(QArrayData), 0, false, true);
+ QArrayData *empty = QArrayData::allocate(1, Q_ALIGNOF(QArrayData), 0);
QVERIFY(null->ref.isStatic());
QVERIFY(null->ref.isSharable());
@@ -473,11 +473,13 @@ struct Deallocator
};
Q_DECLARE_METATYPE(const QArrayData *)
+Q_DECLARE_METATYPE(QArrayData::AllocateOptions)
void tst_QArrayData::allocate_data()
{
QTest::addColumn<size_t>("objectSize");
QTest::addColumn<size_t>("alignment");
+ QTest::addColumn<QArrayData::AllocateOptions>("allocateOptions");
QTest::addColumn<bool>("isCapacityReserved");
QTest::addColumn<bool>("isSharable");
QTest::addColumn<const QArrayData *>("commonEmpty");
@@ -492,22 +494,25 @@ void tst_QArrayData::allocate_data()
{ "void *", sizeof(void *), Q_ALIGNOF(void *) }
};
- QArrayData *shared_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0, false, true);
- QArrayData *unsharable_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0, false, false);
+ QArrayData *shared_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0);
+ QArrayData *unsharable_empty = QArrayData::allocate(0, Q_ALIGNOF(QArrayData), 0, QArrayData::Unsharable);
QVERIFY(shared_empty);
QVERIFY(unsharable_empty);
struct {
char const *description;
+ QArrayData::AllocateOptions allocateOptions;
bool isCapacityReserved;
bool isSharable;
const QArrayData *commonEmpty;
} options[] = {
- { "Default", false, true, shared_empty },
- { "Reserved", true, true, shared_empty },
- { "Reserved | Unsharable", true, false, unsharable_empty },
- { "Unsharable", false, false, unsharable_empty },
+ { "Default", QArrayData::Default, false, true, shared_empty },
+ { "Reserved", QArrayData::CapacityReserved, true, true, shared_empty },
+ { "Reserved | Unsharable",
+ QArrayData::CapacityReserved | QArrayData::Unsharable, true, false,
+ unsharable_empty },
+ { "Unsharable", QArrayData::Unsharable, false, false, unsharable_empty },
};
for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i)
@@ -517,14 +522,15 @@ void tst_QArrayData::allocate_data()
+ QLatin1String(": ")
+ QLatin1String(options[j].description)))
<< types[i].objectSize << types[i].alignment
- << options[j].isCapacityReserved << options[j].isSharable
- << options[j].commonEmpty;
+ << options[j].allocateOptions << options[j].isCapacityReserved
+ << options[j].isSharable << options[j].commonEmpty;
}
void tst_QArrayData::allocate()
{
QFETCH(size_t, objectSize);
QFETCH(size_t, alignment);
+ QFETCH(QArrayData::AllocateOptions, allocateOptions);
QFETCH(bool, isCapacityReserved);
QFETCH(bool, isSharable);
QFETCH(const QArrayData *, commonEmpty);
@@ -535,14 +541,14 @@ void tst_QArrayData::allocate()
// Shared Empty
QCOMPARE(QArrayData::allocate(objectSize, minAlignment, 0,
- isCapacityReserved, isSharable), commonEmpty);
+ QArrayData::AllocateOptions(allocateOptions)), commonEmpty);
Deallocator keeper(objectSize, minAlignment);
keeper.headers.reserve(1024);
for (int capacity = 1; capacity <= 1024; capacity <<= 1) {
QArrayData *data = QArrayData::allocate(objectSize, minAlignment,
- capacity, isCapacityReserved, isSharable);
+ capacity, QArrayData::AllocateOptions(allocateOptions));
keeper.headers.append(data);
QCOMPARE(data->size, 0);
@@ -584,7 +590,7 @@ void tst_QArrayData::alignment()
for (int i = 0; i < 100; ++i) {
QArrayData *data = QArrayData::allocate(sizeof(Unaligned),
- minAlignment, 8, false, true);
+ minAlignment, 8, QArrayData::Default);
keeper.headers.append(data);
QVERIFY(data);
@@ -952,10 +958,14 @@ void tst_QArrayData::setSharable_data()
{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }
};
- QArrayDataPointer<int> emptyReserved(QTypedArrayData<int>::allocate(5, true, true));
- QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(10, false, true));
- QArrayDataPointer<int> nonEmptyReserved(QTypedArrayData<int>::allocate(15, true, true));
- QArrayDataPointer<int> staticArray(static_cast<QTypedArrayData<int> *>(&staticArrayData.header));
+ QArrayDataPointer<int> emptyReserved(QTypedArrayData<int>::allocate(5,
+ QArrayData::CapacityReserved));
+ QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(10,
+ QArrayData::Default));
+ QArrayDataPointer<int> nonEmptyReserved(QTypedArrayData<int>::allocate(15,
+ QArrayData::CapacityReserved));
+ QArrayDataPointer<int> staticArray(
+ static_cast<QTypedArrayData<int> *>(&staticArrayData.header));
nonEmpty->copyAppend(5, 1);
nonEmptyReserved->copyAppend(7, 2);