Martin Cook
Martin Cook

Reputation: 749

Can I monitor boost::lockfree::spsc_queue from a third thread?

I have one thread producing data onto a boost::lockfree::spsc_queue, and one thread consuming data. Can I have a third thread monitoring the queue using read_available or write_available? I am not interested in an accurate count, but I would like to know if the queue is steadily growing, as that means the consumer is not keeping up. The docs state that read_available is:

Thread-safe and wait-free, should only be called from the consumer thread

(https://www.boost.org/doc/libs/1_68_0/doc/html/boost/lockfree/spsc_queue.html)

What happens if a third thread tries to call read_available? If it will just get an inaccurate count, that is fine. If it could get random numbers, or break things in some way, then I think I will keep a count using a std::atomic<int>.

Upvotes: 1

Views: 433

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 364049

You could have the reader thread check the queue size occasionally (like every 1000 items), and publish a std::atomic<int> qsize (with a mo_relaxed store) that the 3rd thread could read.

Use a non-atomic counter that's private to the reader. Reader decrements it, and resets it to 1000 + publishes when it hits zero. Keep it in a cache line that the writer doesn't touch so there's no extra contention at all except every 1000th item you do a store that needs an RFO before it can commit the value to the cache line. But it's a write-only store, not a RMW, so the store buffer can hopefully hide the latency. (Except on x86 where the next atomic RMW is always a full barrier so it will have to wait for that store to commit. But it's only every 1000 dequeue operations so it's barely going to slow the reader down any more.)

Having a std::atomic<int> that both reader and writer atomically inc/dec will make them contend with each other more than a SPSC queue. Not quite as bad as competing for a lock, but I expect it would be much worse than what I suggested.


The details of what happen might depend on the compiler-generated asm for the target machine, and what kind of runtime reordering it can do. I don't know, but if the docs say it's not supported you'd have to investigate or experiment if you want to risk it.

Presumably calling read_available() while the reader is in the middle of dequeuing an element is not safe for some reason.

You'd have to look at the implementation to see if that just means a potential off by one or total garbage.

Upvotes: 1

Related Questions