I have such queue:
boost::lockfree::spsc_queue<orders_log, boost::lockfree::capacity<8192>> futOrdersUpdates;
My problem is that sometimes I deque same item several times. I've added some troubleshoot code:
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
The idea is - if endOfTransaction
flag is not set, I should "spin", otherwise I can exit if queue is empty.
In logs I found strange things:
Expected behavior:
endOfTransaction
flag is not setThe question is - if i'm "dequee" spsc_queue correctly? Any bugs in my code?
We can't possibly know why you are getting duplicates, because we have no idea how you fill replRev
. It could be a data race right there (I hope you don't do lastRev+1
, e.g.).
Note that you likely never get "No items try again" because the loop is skipped entirely, e.g.:
while (bool dequeued = foo())
{
assert(dequeued); // can never be false here!
}
will never even enter the loop.
The reason you get duplicates is because you say
bool dequeued = futOrdersUpdates.pop(entryItem) || !endOfTransaction;
As you know (see your comment) this forces dequeued
to be true
even if no item was dequeued, because endOfTransaction
has not been set yet.
The value of entryItem
is unspecified at that time - but likely just contains the previous value, leading to the "duplicate" message.
For a nice demo using spsc_queue
I recently gave, see this answer: Dynamic generation & safe usage of spsc_queues