提升spsc_queue - 如何"try pop"?

boost spsc_queue - how to "try pop"?

本文关键字:try pop 如何 spsc queue 提升      更新时间:2023-10-16

我有这样的队列:

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

我的问题是,有时我会重复同一项好几次。我添加了一些故障排除代码:

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标志,我应该"旋转",否则我可以在队列为空时退出。

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

  • "没有项目,再试一次"-永远不会出现
  • "重复项目!"-IS出现

预期行为:

  • 当队列为空但未设置endOfTransaction标志时,有时应显示"无项目,重试"
  • "重复项目!"不应出现

问题是,如果我是"dequee"spsc_queue正确吗?我的代码中有漏洞吗?

我们不可能知道您为什么会得到重复项,因为我们不知道如何填充replRev。这可能是一场数据竞赛(例如,我希望你不要做lastRev+1

  1. 请注意,您可能永远不会得到"无项目重试",因为循环被完全跳过,例如:

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

    甚至永远不会进入循环。

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

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

    如您所知(请参阅您的评论),这会强制dequeuedtrue,即使没有项目退出队列,因为endOfTransaction尚未设置。

    entryItem的值是当时未指定的,但可能只包含前一个值,从而导致"重复"消息。

对于我最近给出的使用spsc_queue的一个不错的演示,请参阅以下答案:动态生成&spsc_queues 的安全使用