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:
parent
0e339e2ef5
commit
a4a94544f2
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user