如果这不是 boost::lockfree::detail::freelist 中的错误,我在这里缺少什么?
If this is not a bug in boost::lockfree::detail::freelist, what am I missing here?
在this file, the boost::lockfree::detail::freelist
class is used to manage storage for a lock-free data structure (e.g., a queue), using a free list。
deallocate_impl
方法用于通过将节点链接回空闲列表来释放节点(已释放的节点成为空闲列表的新头,取代旧头)。此方法应该是线程安全且无锁的。此处复制了一个实例的原始源代码,并注释了我的注释以指出可疑代码(潜在错误?):
void deallocate_impl (index_t index)
{
freelist_node * new_pool_node =
reinterpret_cast<freelist_node*>(NodeStorage::nodes() + index);
// Shouldn't this line be placed inside the loop?
// The loop continues as long as the compare-and-exchange fails,
// which happens if the pool head has been concurrently updated.
// In that case, we MUST reload the new value of "pool_" to
// reuse its tag, link the new free-list head to it and
// compare against in the compare_and_exchange call.
tagged_index old_pool = pool_.load(memory_order_consume);
for(;;) {
// The old pool head tag is reused here without causing
// any ABA problems. However, if "index" is the same as
// old_pool.get_index(), a self-reference is written.
tagged_index new_pool (index, old_pool.get_tag());
new_pool_node->next.set_index(old_pool.get_index());
if (pool_.compare_exchange_weak(old_pool, new_pool))
return;
}
}
我在 Boost 1.62.0 中也看到了相同的实现
The loop continues as long as the compare-and-exchange fails, which happens if the pool head has been concurrently updated. In that case, we MUST reload the new value of "pool_" to reuse its tag...
compare_exchange_weak()
在每次调用后将 pool_
的先前值写入 old_pool
。 Documentation for compare_exchange_weak()
.
However, if "index" is the same as old_pool.get_index()...
这可能不会发生,因为具有该索引的节点尚未移至空闲列表。
在this file, the boost::lockfree::detail::freelist
class is used to manage storage for a lock-free data structure (e.g., a queue), using a free list。
deallocate_impl
方法用于通过将节点链接回空闲列表来释放节点(已释放的节点成为空闲列表的新头,取代旧头)。此方法应该是线程安全且无锁的。此处复制了一个实例的原始源代码,并注释了我的注释以指出可疑代码(潜在错误?):
void deallocate_impl (index_t index)
{
freelist_node * new_pool_node =
reinterpret_cast<freelist_node*>(NodeStorage::nodes() + index);
// Shouldn't this line be placed inside the loop?
// The loop continues as long as the compare-and-exchange fails,
// which happens if the pool head has been concurrently updated.
// In that case, we MUST reload the new value of "pool_" to
// reuse its tag, link the new free-list head to it and
// compare against in the compare_and_exchange call.
tagged_index old_pool = pool_.load(memory_order_consume);
for(;;) {
// The old pool head tag is reused here without causing
// any ABA problems. However, if "index" is the same as
// old_pool.get_index(), a self-reference is written.
tagged_index new_pool (index, old_pool.get_tag());
new_pool_node->next.set_index(old_pool.get_index());
if (pool_.compare_exchange_weak(old_pool, new_pool))
return;
}
}
我在 Boost 1.62.0 中也看到了相同的实现
The loop continues as long as the compare-and-exchange fails, which happens if the pool head has been concurrently updated. In that case, we MUST reload the new value of "pool_" to reuse its tag...
compare_exchange_weak()
在每次调用后将 pool_
的先前值写入 old_pool
。 Documentation for compare_exchange_weak()
.
However, if "index" is the same as old_pool.get_index()...
这可能不会发生,因为具有该索引的节点尚未移至空闲列表。