Hi I am trying to understand lock-free work stealing dequeue implementation. Currently, I am reading one implementation by google's filament here. I am mostly concerned about the steal operation.
template <typename TYPE, size_t COUNT>
TYPE WorkStealingDequeue<TYPE, COUNT>::steal() noexcept {
do {
// mTop must be read before mBottom
int32_t top = mTop.load(std::memory_order_seq_cst);
// mBottom is written concurrently to the read below in pop() or push(), so
// we need basic atomicity. Also makes sure that writes made in push()
// (prior to mBottom update) are visible.
int32_t bottom = mBottom.load(std::memory_order_acquire);
if (top >= bottom) {
// queue is empty
return TYPE();
}
// The queue isn't empty
TYPE item(getItemAt(top));
if (mTop.compare_exchange_strong(top, top + 1,
std::memory_order_seq_cst,
std::memory_order_relaxed)) {
// success: we stole a job, just return it.
return item;
}
// failure: the item we just tried to steal was pop()'ed under our feet,
// simply discard it; nothing to do.
} while (true);
}
I am wondering whether it's correct to replace the initial mtop.load memory order to memory_order_relaxed and the subsequent mBottom.load memory order to memory_order_seq_cst. This should still preserve the mtop.load and mBottom.load order right? memory_order_seq_cst flag should still prevent memory_order_relaxed to be reordered pass the the load operation right?