Introduce QArrayData::detachCapacity
authorJoão Abecasis <joao.abecasis@nokia.com>
Mon, 5 Mar 2012 16:43:34 +0000 (17:43 +0100)
committerQt by Nokia <qt-info@nokia.com>
Mon, 2 Apr 2012 14:34:21 +0000 (16:34 +0200)
This follows QArrayData::detachFlags's lead. Given the (known) size for
a detached container, the function helps determine capacity, ensuring
the capacityReserved flag is respected.

This further helps aggregating behaviour on detach in QArrayData itself.

SimpleVector was previously using qMax(capacity(), newSize), but there's
no reason to pin the previous capacity value if reserve() wasn't
requested. It now uses detachCapacity().

Change-Id: Ide2d99ea7ecd2cd98ae4c1aa397b4475d09c8485
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/tools/qarraydata.h
src/corelib/tools/qarraydatapointer.h
tests/auto/corelib/tools/qarraydata/simplevector.h
tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp

index ae4cbc3..78fbc9c 100644 (file)
@@ -91,6 +91,13 @@ struct Q_CORE_EXPORT QArrayData
 
     Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)
 
+    size_t detachCapacity(size_t newSize) const
+    {
+        if (capacityReserved && newSize < alloc)
+            return alloc;
+        return newSize;
+    }
+
     AllocationOptions detachFlags() const
     {
         AllocationOptions result;
index f5ad53a..4eb90ac 100644 (file)
@@ -171,7 +171,7 @@ public:
 private:
     Data *clone(QArrayData::AllocationOptions options) const Q_REQUIRED_RESULT
     {
-        QArrayDataPointer copy(Data::allocate(d->alloc ? d->alloc : d->size,
+        QArrayDataPointer copy(Data::allocate(d->detachCapacity(d->size),
                     options));
         if (d->size)
             copy->copyAppend(d->begin(), d->end());
index 0cc7561..54c9fae 100644 (file)
@@ -184,7 +184,7 @@ public:
         if (d->ref.isShared()
                 || capacity() - size() < size_t(last - first)) {
             SimpleVector detached(Data::allocate(
-                        qMax(capacity(), size() + (last - first)),
+                        d->detachCapacity(size() + (last - first)),
                         d->detachFlags() | Data::Grow));
 
             detached.d->copyAppend(first, last);
@@ -205,7 +205,7 @@ public:
         if (d->ref.isShared()
                 || capacity() - size() < size_t(last - first)) {
             SimpleVector detached(Data::allocate(
-                        qMax(capacity(), size() + (last - first)),
+                        d->detachCapacity(size() + (last - first)),
                         d->detachFlags() | Data::Grow));
 
             if (d->size) {
@@ -245,7 +245,7 @@ public:
         if (d->ref.isShared()
                 || capacity() - size() < size_t(last - first)) {
             SimpleVector detached(Data::allocate(
-                        qMax(capacity(), size() + (last - first)),
+                        d->detachCapacity(size() + (last - first)),
                         d->detachFlags() | Data::Grow));
 
             if (position)
index 6d3bbf0..b3b8040 100644 (file)
@@ -1175,8 +1175,10 @@ void tst_QArrayData::setSharable_data()
 
     QArrayDataPointer<int> emptyReserved(QTypedArrayData<int>::allocate(5,
                 QArrayData::CapacityReserved));
-    QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(10,
+    QArrayDataPointer<int> nonEmpty(QTypedArrayData<int>::allocate(5,
                 QArrayData::Default));
+    QArrayDataPointer<int> nonEmptyExtraCapacity(
+            QTypedArrayData<int>::allocate(10, QArrayData::Default));
     QArrayDataPointer<int> nonEmptyReserved(QTypedArrayData<int>::allocate(15,
                 QArrayData::CapacityReserved));
     QArrayDataPointer<int> staticArray(
@@ -1185,13 +1187,15 @@ void tst_QArrayData::setSharable_data()
             QTypedArrayData<int>::fromRawData(staticArrayData.data, 10));
 
     nonEmpty->copyAppend(5, 1);
+    nonEmptyExtraCapacity->copyAppend(5, 1);
     nonEmptyReserved->copyAppend(7, 2);
 
     QTest::newRow("shared-null") << null << size_t(0) << size_t(0) << false << 0;
     QTest::newRow("shared-empty") << empty << size_t(0) << size_t(0) << false << 0;
     // unsharable-empty implicitly tested in shared-empty
     QTest::newRow("empty-reserved") << emptyReserved << size_t(0) << size_t(5) << true << 0;
-    QTest::newRow("non-empty") << nonEmpty << size_t(5) << size_t(10) << false << 1;
+    QTest::newRow("non-empty") << nonEmpty << size_t(5) << size_t(5) << false << 1;
+    QTest::newRow("non-empty-extra-capacity") << nonEmptyExtraCapacity << size_t(5) << size_t(10) << false << 1;
     QTest::newRow("non-empty-reserved") << nonEmptyReserved << size_t(7) << size_t(15) << true << 2;
     QTest::newRow("static-array") << staticArray << size_t(10) << size_t(0) << false << 3;
     QTest::newRow("raw-data") << rawData << size_t(10) << size_t(0) << false << 3;
@@ -1229,8 +1233,10 @@ void tst_QArrayData::setSharable()
     // Unshare, must detach
     array.setSharable(false);
 
-    // Immutability (alloc == 0) is lost on detach
-    if (capacity == 0 && size != 0)
+    // Immutability (alloc == 0) is lost on detach, as is additional capacity
+    // if capacityReserved flag is not set.
+    if ((capacity == 0 && size != 0)
+            || (!isCapacityReserved && capacity > size))
         capacity = size;
 
     QVERIFY(!array->ref.isShared());