【问题标题】:If this is not a bug in boost::lockfree::detail::freelist, what am I missing here?如果这不是 boost::lockfree::detail::freelist 中的错误,那么我在这里缺少什么?
【发布时间】:2017-03-20 17:18:46
【问题描述】:

this file 中,boost::lockfree::detail::freelist 类用于使用free list 管理无锁数据结构(例如队列)的存储。 deallocate_impl 方法用于通过将节点链接回空闲列表来释放节点(释放的节点成为空闲列表的新头,取代旧头)。这种方法应该是线程安全和无锁的。此处复制了一个实例的原始源代码,并注释了我的 cmets 以指出可疑代码(潜在错误?):

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 中也看到了相同的实现

【问题讨论】:

  • c++ 的一大缺点是不表示在调用站点通过引用成员传递。比较交换更新期望值与当前可见的值
  • 谢谢你,@Voo。

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


【解决方案1】:

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

compare_exchange_weak() 在每次调用后将pool_ 的先前值写入old_poolDocumentation for compare_exchange_weak().

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

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

【讨论】:

  • 谢谢@Grisha。我应该在发布问题之前查看文档。
猜你喜欢
  • 1970-01-01
  • 2020-09-21
  • 2010-12-24
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多