Don't use implicit QAtomic* casts in QFreeList
authorBradley T. Hughes <bradley.hughes@nokia.com>
Thu, 29 Sep 2011 09:45:01 +0000 (11:45 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 5 Oct 2011 14:31:37 +0000 (16:31 +0200)
Pair the _next.testAndSetRelease() call in QFreeList<T>::release() with
_next.loadAcquire(), to ensure that the update to the bucket
being released is properly fenced.

QFreeList<T>:next() does not need a release fence, only an acquire fence,
which is placed on the memory bucket address load.

Change-Id: Ib5b9d6ef6107f87aa8e3ea2dd3a7f9116c75da70
Reviewed-by: Thiago Macieira
Reviewed-on: http://codereview.qt-project.org/5802
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
src/corelib/tools/qfreelist_p.h

index 74ba3b5..5af0bb1 100644 (file)
@@ -218,21 +218,21 @@ template <typename T, typename ConstantsType>
 inline QFreeList<T, ConstantsType>::~QFreeList()
 {
     for (int i = 0; i < ConstantsType::BlockCount; ++i)
-        delete [] static_cast<ElementType *>(_v[i]);
+        delete [] _v[i].load();
 }
 
 template <typename T, typename ConstantsType>
 inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
 {
     const int block = blockfor(x);
-    return _v[block][x].t();
+    return (_v[block].load())[x].t();
 }
 
 template <typename T, typename ConstantsType>
 inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
 {
     const int block = blockfor(x);
-    return _v[block][x].t();
+    return (_v[block].load())[x].t();
 }
 
 template <typename T, typename ConstantsType>
@@ -241,24 +241,24 @@ inline int QFreeList<T, ConstantsType>::next()
     int id, newid, at;
     ElementType *v;
     do {
-        id = _next; // .loadAqcuire();
+        id = _next.load();
 
         at = id & ConstantsType::IndexMask;
         const int block = blockfor(at);
-        v = _v[block];
+        v = _v[block].loadAcquire();
 
         if (!v) {
             v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
             if (!_v[block].testAndSetRelease(0, v)) {
                 // race with another thread lost
                 delete [] v;
-                v = _v[block];
+                v = _v[block].loadAcquire();
                 Q_ASSERT(v != 0);
             }
         }
 
         newid = v[at].next | (id & ~ConstantsType::IndexMask);
-    } while (!_next.testAndSetRelease(id, newid));
+    } while (!_next.testAndSetRelaxed(id, newid));
     // qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
     //        id & ConstantsType::IndexMask,
     //        newid & ConstantsType::IndexMask,
@@ -271,11 +271,11 @@ inline void QFreeList<T, ConstantsType>::release(int id)
 {
     int at = id & ConstantsType::IndexMask;
     const int block = blockfor(at);
-    ElementType *v = _v[block];
+    ElementType *v = _v[block].load();
 
     int x, newid;
     do {
-        x = _next; // .loadAcquire();
+        x = _next.loadAcquire();
         v[at].next = x & ConstantsType::IndexMask;
 
         newid = incrementserial(x, id);