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()
|
inline QFreeList<T, ConstantsType>::~QFreeList()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ConstantsType::BlockCount; ++i)
|
for (int i = 0; i < ConstantsType::BlockCount; ++i)
|
||||||
delete [] static_cast<ElementType *>(_v[i]);
|
delete [] _v[i].load();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ConstantsType>
|
template <typename T, typename ConstantsType>
|
||||||
inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
|
inline typename QFreeList<T, ConstantsType>::ConstReferenceType QFreeList<T, ConstantsType>::at(int x) const
|
||||||
{
|
{
|
||||||
const int block = blockfor(x);
|
const int block = blockfor(x);
|
||||||
return _v[block][x].t();
|
return (_v[block].load())[x].t();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ConstantsType>
|
template <typename T, typename ConstantsType>
|
||||||
inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
|
inline typename QFreeList<T, ConstantsType>::ReferenceType QFreeList<T, ConstantsType>::operator[](int x)
|
||||||
{
|
{
|
||||||
const int block = blockfor(x);
|
const int block = blockfor(x);
|
||||||
return _v[block][x].t();
|
return (_v[block].load())[x].t();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ConstantsType>
|
template <typename T, typename ConstantsType>
|
||||||
@ -241,24 +241,24 @@ inline int QFreeList<T, ConstantsType>::next()
|
|||||||
int id, newid, at;
|
int id, newid, at;
|
||||||
ElementType *v;
|
ElementType *v;
|
||||||
do {
|
do {
|
||||||
id = _next; // .loadAqcuire();
|
id = _next.load();
|
||||||
|
|
||||||
at = id & ConstantsType::IndexMask;
|
at = id & ConstantsType::IndexMask;
|
||||||
const int block = blockfor(at);
|
const int block = blockfor(at);
|
||||||
v = _v[block];
|
v = _v[block].loadAcquire();
|
||||||
|
|
||||||
if (!v) {
|
if (!v) {
|
||||||
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
|
v = allocate((id & ConstantsType::IndexMask) - at, ConstantsType::Sizes[block]);
|
||||||
if (!_v[block].testAndSetRelease(0, v)) {
|
if (!_v[block].testAndSetRelease(0, v)) {
|
||||||
// race with another thread lost
|
// race with another thread lost
|
||||||
delete [] v;
|
delete [] v;
|
||||||
v = _v[block];
|
v = _v[block].loadAcquire();
|
||||||
Q_ASSERT(v != 0);
|
Q_ASSERT(v != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newid = v[at].next | (id & ~ConstantsType::IndexMask);
|
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)",
|
// qDebug("QFreeList::next(): returning %d (_next now %d, serial %d)",
|
||||||
// id & ConstantsType::IndexMask,
|
// id & ConstantsType::IndexMask,
|
||||||
// newid & ConstantsType::IndexMask,
|
// newid & ConstantsType::IndexMask,
|
||||||
@ -271,11 +271,11 @@ inline void QFreeList<T, ConstantsType>::release(int id)
|
|||||||
{
|
{
|
||||||
int at = id & ConstantsType::IndexMask;
|
int at = id & ConstantsType::IndexMask;
|
||||||
const int block = blockfor(at);
|
const int block = blockfor(at);
|
||||||
ElementType *v = _v[block];
|
ElementType *v = _v[block].load();
|
||||||
|
|
||||||
int x, newid;
|
int x, newid;
|
||||||
do {
|
do {
|
||||||
x = _next; // .loadAcquire();
|
x = _next.loadAcquire();
|
||||||
v[at].next = x & ConstantsType::IndexMask;
|
v[at].next = x & ConstantsType::IndexMask;
|
||||||
|
|
||||||
newid = incrementserial(x, id);
|
newid = incrementserial(x, id);
|
||||||
|
Loading…
Reference in New Issue
Block a user