Don't use implicit QAtomic* casts in QFreeList

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>
This commit is contained in:
Bradley T. Hughes 2011-09-29 11:45:01 +02:00 committed by Qt by Nokia
parent 0e339e2ef5
commit a4a94544f2

View 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);