-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
util: UdpFramed takes Borrow<UdpSocket> #3451
Conversation
tokio-util/src/udp/frame.rs
Outdated
pub struct UdpFramed<C> { | ||
socket: UdpSocket, | ||
pub struct UdpFramed<T, C> { | ||
socket: T, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change, and would require a new tokio-util series.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, although I don't see any other way to enable this:
let a = Arc::new(UdpSocket::bind("127.0.0.1:0").await?);
let b = Arc::clone(&a);
let mut recv = UdpFramed::new(a, ByteCodec);
let mut send = UdpFramed::new(b, ByteCodec);
// possibly move recv/send to different tasks
I think it's a fairly common scenario that you'll have a UdpSocket
in an Arc
in order to share between different tasks? You may want to have one task doing the sending and one doing the recv'ing for example.
Would it help if it was a new type instead of changing UdpFramed
?
edit: Just to make my case a little further. I the old api of taking just UdpSocket
made more sense when tokio required &mut self
to send/recv. Now that it's &self
, I think this API makes more sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be possible to add it with a default as in UdpFramed<C, T = UdpSocket>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll experiment with that and report back. Probably best to switch the type param order as you have there also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seemed to work. I was also able to add back get_mut
by writing an impl block specifically for UdpFramed<C, T> where T: BorrowMut<UdpSocket>
since BorrowMut
is a parent trait to Borrow
it will have access to all the other methods also.
82ce761
to
57ef66d
Compare
327064d
to
669cece
Compare
You will probably need to merge or rebase on master to get the fixes for any warnings introduced to Rust after this PR was created. |
669cece
to
2470a8b
Compare
Should be all up to date now. |
tokio-util/src/udp/frame.rs
Outdated
impl<C: Decoder + Unpin> Stream for UdpFramed<C> { | ||
impl<C, T> Stream for UdpFramed<C, T> | ||
where | ||
T: Borrow<UdpSocket> + Unpin, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not need the Unpin
bound.
T: Borrow<UdpSocket> + Unpin, | |
T: Borrow<UdpSocket>, |
You can even add an unconditional impl<C, T> Unpin for UdpFramed<C, T> {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That last impl is what I was missing, without it the self.get_mut()
line in Stream
complains about Unpin
. Thanks!
tokio-util/src/udp/frame.rs
Outdated
@@ -79,7 +86,7 @@ impl<C: Decoder + Unpin> Stream for UdpFramed<C> { | |||
let buf = &mut *(pin.rd.chunk_mut() as *mut _ as *mut [MaybeUninit<u8>]); | |||
let mut read = ReadBuf::uninit(buf); | |||
let ptr = read.filled().as_ptr(); | |||
let res = ready!(Pin::new(&mut pin.socket).poll_recv_from(cx, &mut read)); | |||
let res = ready!(Pin::new(&mut pin.socket.borrow()).poll_recv_from(cx, &mut read)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let res = ready!(Pin::new(&mut pin.socket.borrow()).poll_recv_from(cx, &mut read)); | |
let res = ready!(pin.socket.borrow().poll_recv_from(cx, &mut read)); |
tokio-util/src/udp/frame.rs
Outdated
T: Borrow<UdpSocket> + Unpin, | ||
C: Encoder<I> + Unpin, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, you don't need Unpin
here.
T: Borrow<UdpSocket> + Unpin, | |
C: Encoder<I> + Unpin, | |
T: Borrow<UdpSocket>, | |
C: Encoder<I>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added these and the above changes manually, I just want to call out that the previous bound was C: Encoder<I> + Unpin
so we are removing an existing Unpin
bound also, same with C: Decoder + Unpin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, well, there should not have been any Unpin
bounds in this file in the first place.
tokio-util/src/udp/frame.rs
Outdated
/// with. | ||
pub fn get_mut(&mut self) -> &mut UdpSocket { | ||
&mut self.socket | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you remove get_mut
, it becomes a breaking change. Maybe return &mut T
here, then change get_ref
to return &T
for consistency.
Edit: I just noticed the get_mut
impl further down. Not sure what I like best tbh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with either, I used .borrow()
and .borrow_mut()
because I thought it may be a breaking change if it returned &T
and a user updated, all of a sudden you have to call .borrow()
additionally on that to get a &UdpSocket
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, any existing users would have T = UdpSocket
, so if we return &T
, that's an &UdpSocket
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default param was a recent addition that changes things, good point. Okay, I've updated it to return the type params.
0cf146b
to
d5b492c
Compare
d5b492c
to
a5148bd
Compare
Motivation
This changes
UdpFramed
from holding aUdpSocket
to aBorrow<UdpSocket>
.Often, you will have an
Arc<UdpSocket>
which you want to share among many tasks but also still be able to use the helper functions fromtokio-util
. Unfortunately,UdpFramed
only takes aUdpSocket
.The disadvantage of this approach is thatinto_inner
andget_mut
must be removed, does that seem like an acceptable trade-off for the added flexibility?edit:
into_inner
doesn't actually have to be removed,my mistake, onlyget_mut
edit:
get_mut
now implemented specifically forUdpFramed<C, UdpSocket>
Possible Solution?
Make
UdpFramed
take aT: Borrow<UdpSocket>
so it can take UdpSocket types generically.I'm happy to take any feedback or alternate approach that is suggested. But let me take your temperature first on if you think you'd like this change or not?