boost spsc_queue - 如何“尝试流行”?

时间:2014-04-24 13:59:50

标签: c++ boost lock-free

我有这样的队列:

    boost::lockfree::spsc_queue<orders_log,  boost::lockfree::capacity<8192>> futOrdersUpdates;

我的问题是,有时我会多次将同一项目deque。我添加了一些疑难解答代码:

while (bool dequeued = futOrdersUpdates.pop(entryItem) || !endOfTransaction)
{
    if (!dequeued) {
        dequeueLoger.Debug("no items, try again");
        continue;
    } else {
        if (lastRev != 0 && entryItem.replRev == lastRev) {
            dequeueLoger.Debug("duplicate item!");
        }
        lastRev = entryItem.replRev;
    }
            // further processing

这个想法是 - 如果没有设置endOfTransaction标志,我应该“旋转”,否则我可以在队列为空时退出。

在日志中我发现了一些奇怪的东西:

  • “没有项目,请再试一次” - 绝不会出现
  • “重复项目!” - 出现了。

预期行为:

  • “没有项目,请再试一次”有时会出现 - 当队列为空但未设置endOfTransaction标志时
  • “重复项目!”永远不应该出现

问题是 - 如果我正确地“解压缩”spsc_queue?我的代码中有任何错误吗?

1 个答案:

答案 0 :(得分:0)

我们无法知道你为什么要重复,因为我们不知道你如何填补replRev。这可能是一场数据竞赛(我希望你不要做lastRev+1,例如)。

  1. 请注意,您可能永远不会得到&#34;没有项目会再次尝试&#34;因为循环被完全跳过,例如:

    while (bool dequeued = foo())
    {  
         assert(dequeued); // can never be false here!
    }
    

    永远不会进入循环。

  2. 你得到重复的原因是因为你说

    bool dequeued = futOrdersUpdates.pop(entryItem) || !endOfTransaction;
    

    如您所知(请参阅您的评论),即使没有项 出列,强制 dequeued仍为true,因为{{1尚未设置。

    此时endOfTransaction的值未指定 - 但可能只包含之前的值,导致&#34;重复&#34;消息。

  3. 对于我最近给出的entryItem的精彩演示,请参阅此答案:Dynamic generation & safe usage of spsc_queues