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

rtic-sync: deal with dropping & re-splitting channels. #1040

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

datdenkikniet
Copy link
Contributor

@datdenkikniet datdenkikniet commented Mar 17, 2025

Currently split-ing a channel is technically allowed, but there is no non-panic way of actually doing so.

Currently it will either panic if freeq is full (and readyq is empty), or succesfully re-split and always produce Err(NoReceiver) when sending, and/or panic eventually when returning a free slot while recv-ing.

Additionally, items in the ready queue are never dropped if the channel is dropped.

This is not a particularly often-used use-case, but that doesn't mean we cannot try fixing it :)

An alternative approach is to just have a split: bool in the Channel and always panic if that bool is already set, or always calling Channel::clear when split-ing.

To see concrete use-cases that this PR fixes, please check out the introduced tests.

@datdenkikniet datdenkikniet force-pushed the multi-split branch 4 times, most recently from 52a2ac5 to 082859b Compare March 19, 2025 19:44
Copy link
Collaborator

@korken89 korken89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, thank you! Just some minor comments.

pub fn split(&mut self) -> (Sender<'_, T, N>, Receiver<'_, T, N>) {
assert!(
self.readyq.get_mut().is_empty(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have &mut channel here, can't we do self.clear()?

Copy link
Contributor Author

@datdenkikniet datdenkikniet Mar 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we could. When writing this felt weird to drop the items in the queue on split, but not any earlier. Since most callers won't ever re-split() their queue I figured we could get away with never calling clear if they do not.

If you think we should clear(), should we do it in Receiver::drop too? It just feels kind of arbitrary to drop leftover items on split() and not earlier (i.e. Receiver::drop), but I have no clue what the usual thing to do is, here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have rebased on the latest master. Any opinions on the above?

@datdenkikniet datdenkikniet force-pushed the multi-split branch 3 times, most recently from f464616 to 2f7b3c1 Compare March 24, 2025 19:34
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

Successfully merging this pull request may close these issues.

2 participants