如果这不是boost :: lockfree :: detail :: freelist中的错误,我在这里缺少什么?

时间:2017-03-20 17:18:46

标签: c++ multithreading boost queue lock-free

this file中,deallocate_impl类用于使用free list管理无锁数据结构(例如,队列)的存储。 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; } } 方法用于通过将节点链接回空闲列表来释放节点(释放的节点成为空闲列表的新头,取代旧头)。该方法应该是线程安全且无锁定的。一个实例的原始源代码在这里重复,我的注释注释指出可疑代码(潜在的错误?):

{{1}}

我在Boost 1.62.0中也看到了相同的实现

1 个答案:

答案 0 :(得分:2)

  

只要比较和交换失败,循环就会继续,如果池头已同时更新,则会发生这种情况。在这种情况下,我们必须重新加载“pool_”的新值以重用其标记...

每次通话后,

compare_exchange_weak()会将pool_的先前值写入old_poolDocumentation for compare_exchange_weak()

  

但是,如果“index”与old_pool.get_index()...

相同

这可能不会发生,因为具有该索引的节点尚未移动到空闲列表。