Use RefCount::setSharable feature in QVector
authorJoão Abecasis <joao.abecasis@nokia.com>
Mon, 31 Oct 2011 14:30:20 +0000 (15:30 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 10 Jan 2012 13:43:15 +0000 (14:43 +0100)
Note: This constitutes a break in Binary Compatibility.

Change-Id: I050587901725b701f20dd46475ae48aec28aa54d
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
src/corelib/tools/qvector.cpp
src/corelib/tools/qvector.h
tests/benchmarks/corelib/tools/qvector/qrawvector.h

index 95ae76e..d4c7fd7 100644 (file)
@@ -52,7 +52,7 @@ static inline int alignmentThreshold()
     return 2 * sizeof(void*);
 }
 
-const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, true, false, 0 };
+const QVectorData QVectorData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, 0 };
 
 QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init)
 {
index f408f65..f9db421 100644 (file)
@@ -70,13 +70,11 @@ struct Q_CORE_EXPORT QVectorData
     int size;
 #if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
     // workaround for bug in gcc 3.4.2
-    uint sharable;
     uint capacity;
     uint reserved;
 #else
-    uint sharable : 1;
     uint capacity : 1;
-    uint reserved : 30;
+    uint reserved : 31;
 #endif
 
     static const QVectorData shared_null;
@@ -120,7 +118,19 @@ public:
     inline QVector() : d(const_cast<QVectorData *>(&QVectorData::shared_null)) { }
     explicit QVector(int size);
     QVector(int size, const T &t);
-    inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+    inline QVector(const QVector<T> &v)
+    {
+        if (v.d->ref.ref()) {
+            d = v.d;
+        } else {
+            d = const_cast<QVectorData *>(&QVectorData::shared_null);
+            realloc(0, v.d->alloc);
+            qCopy(v.p->array, v.p->array + v.d->size, p->array);
+            d->size = v.d->size;
+            d->capacity = v.d->capacity;
+        }
+    }
+
     inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
     QVector<T> &operator=(const QVector<T> &v);
 #ifdef Q_COMPILER_RVALUE_REFS
@@ -144,9 +154,18 @@ public:
     void reserve(int size);
     inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; }
 
-    inline void detach() { if (d->ref != 1) detach_helper(); }
-    inline bool isDetached() const { return d->ref == 1; }
-    inline void setSharable(bool sharable) { if (!sharable) detach(); if (d != &QVectorData::shared_null) d->sharable = sharable; }
+    inline void detach() { if (!isDetached()) detach_helper(); }
+    inline bool isDetached() const { return !d->ref.isShared(); }
+    inline void setSharable(bool sharable)
+    {
+        if (sharable == d->ref.isSharable())
+            return;
+        if (!sharable)
+            detach();
+        if (d != &QVectorData::shared_null)
+            d->ref.setSharable(sharable);
+    }
+
     inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
 
     inline T *data() { detach(); return p->array; }
@@ -337,7 +356,7 @@ void QVector<T>::detach_helper()
 { realloc(d->size, d->alloc); }
 template <typename T>
 void QVector<T>::reserve(int asize)
-{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; }
+{ if (asize > d->alloc) realloc(d->size, asize); if (isDetached()) d->capacity = 1; }
 template <typename T>
 void QVector<T>::resize(int asize)
 { realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ?
@@ -389,13 +408,10 @@ inline void QVector<T>::replace(int i, const T &t)
 template <typename T>
 QVector<T> &QVector<T>::operator=(const QVector<T> &v)
 {
-    QVectorData *o = v.d;
-    o->ref.ref();
-    if (!d->ref.deref())
-        free(p);
-    d = o;
-    if (!d->sharable)
-        detach_helper();
+    if (v.d != d) {
+        QVector<T> tmp(v);
+        tmp.swap(*this);
+    }
     return *this;
 }
 
@@ -413,7 +429,6 @@ QVector<T>::QVector(int asize)
     d = malloc(asize);
     d->ref.initializeOwned();
     d->alloc = d->size = asize;
-    d->sharable = true;
     d->capacity = false;
     if (QTypeInfo<T>::isComplex) {
         T* b = p->array;
@@ -431,7 +446,6 @@ QVector<T>::QVector(int asize, const T &t)
     d = malloc(asize);
     d->ref.initializeOwned();
     d->alloc = d->size = asize;
-    d->sharable = true;
     d->capacity = false;
     T* i = p->array + d->size;
     while (i != p->array)
@@ -445,7 +459,6 @@ QVector<T>::QVector(std::initializer_list<T> args)
     d = malloc(int(args.size()));
     d->ref.initializeOwned();
     d->alloc = d->size = int(args.size());
-    d->sharable = true;
     d->capacity = false;
     T* i = p->array + d->size;
     auto it = args.end();
@@ -477,7 +490,7 @@ void QVector<T>::realloc(int asize, int aalloc)
     union { QVectorData *d; Data *p; } x;
     x.d = d;
 
-    if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
+    if (QTypeInfo<T>::isComplex && asize < d->size && isDetached()) {
         // call the destructor on all objects that need to be
         // destroyed when shrinking
         pOld = p->array + d->size;
@@ -488,13 +501,13 @@ void QVector<T>::realloc(int asize, int aalloc)
         }
     }
 
-    if (aalloc != d->alloc || d->ref != 1) {
+    if (aalloc != d->alloc || !isDetached()) {
         // (re)allocate memory
         if (QTypeInfo<T>::isStatic) {
             x.d = malloc(aalloc);
             Q_CHECK_PTR(x.p);
             x.d->size = 0;
-        } else if (d->ref != 1) {
+        } else if (!isDetached()) {
             x.d = malloc(aalloc);
             Q_CHECK_PTR(x.p);
             if (QTypeInfo<T>::isComplex) {
@@ -517,7 +530,6 @@ void QVector<T>::realloc(int asize, int aalloc)
         }
         x.d->ref.initializeOwned();
         x.d->alloc = aalloc;
-        x.d->sharable = true;
         x.d->capacity = d->capacity;
         x.d->reserved = 0;
     }
@@ -572,7 +584,7 @@ Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
 template <typename T>
 void QVector<T>::append(const T &t)
 {
-    if (d->ref != 1 || d->size + 1 > d->alloc) {
+    if (!isDetached() || d->size + 1 > d->alloc) {
         const T copy(t);
         realloc(d->size, (d->size + 1 > d->alloc) ?
                     QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), QTypeInfo<T>::isStatic)
@@ -596,7 +608,7 @@ Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n,
     int offset = int(before - p->array);
     if (n != 0) {
         const T copy(t);
-        if (d->ref != 1 || d->size + n > d->alloc)
+        if (!isDetached() || d->size + n > d->alloc)
             realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
                                                QTypeInfo<T>::isStatic));
         if (QTypeInfo<T>::isStatic) {
index f786d83..2cdabb3 100644 (file)
@@ -292,7 +292,6 @@ public:
         d->ref.initializeOwned();
         d->alloc = m_alloc;
         d->size = m_size;
-        d->sharable = 0;
         d->capacity = 0;
 
         QVector<T> v;