bus icon indicating copy to clipboard operation
bus copied to clipboard

Non-blocking destructive bus

Open gyscos opened this issue 4 years ago • 3 comments

Hi!

I have a need for a non-blocking sender. When the bus is full, I'd like to overwrite oldest non-read elements (so readers might skip items if they're too slow) rather than blocking. Bus::try_broadcast is not working for me since I still need to send the new message when the bus is full.

Is it something this library might add?

gyscos avatar Jul 11 '19 22:07 gyscos

Hmm, that's an interesting feature... It'd be pretty tricky to add, because the value may already have gone out to some readers, and others may be accessing it concurrently. I think doing this in a race-free way would be pretty tough. If you have an idea for how to do it though, I'd be happy to take a look at a PR!

jonhoo avatar Jul 11 '19 22:07 jonhoo

I'm still reading through the code, so I have an incomplete view, but I think it would go like that:

  • We need an atomic counter (called num_readers) and an atomic bool (called writer_waiting).
  • When a reader wants to receive a value:
    • It spins-lock until writer_waiting is false
    • It increases num_readers
    • If the head pointer is higher than the reader pointer, update the reader pointer to the head pointer.
    • It copies the value out of the bus
    • It decreases num_readers
  • When a writer wants to send a value and the bus is full:
    • It spin-locks until writer_waiting.compare_and_swap(false, true) returns false
    • It spin-lock until num_readers is 0 (should be the duration of a few memcopys)
    • It overwrites the oldest value
    • It updates the head/tail pointers
    • It sets writer_waiting to false

The counter and bool might be replaced by a RWLock.

This ensures that no-one is reading the cell we are overwriting, and limits the time the writer waits (to the time taken by mem-copying the value out of the bus by the outstanding readers).

I'm not 100% sure it should share the code of the current implementation: it risk adding complexity/overhead to cases where it's not needed, while not benefiting from features of the current implementation. :S

gyscos avatar Jul 12 '19 16:07 gyscos

Hmm, yeah, I'd worry that this would end up adding significant contention for both reads and writes, which is something the current implementation tries very hard to avoid. It could be that it should be its own implementation that we can optimize separately?

jonhoo avatar Jul 12 '19 17:07 jonhoo