Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-blocking destructive bus #21

Open
gyscos opened this issue Jul 11, 2019 · 3 comments
Open

Non-blocking destructive bus #21

gyscos opened this issue Jul 11, 2019 · 3 comments

Comments

@gyscos
Copy link

gyscos commented Jul 11, 2019

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?

@jonhoo
Copy link
Owner

jonhoo commented Jul 11, 2019

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!

@gyscos
Copy link
Author

gyscos commented Jul 12, 2019

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

@jonhoo
Copy link
Owner

jonhoo commented Jul 12, 2019

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants