-
Notifications
You must be signed in to change notification settings - Fork 41
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
added Receiver::recv_owned
#83
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -580,6 +580,19 @@ impl<T> Receiver<T> { | |
}) | ||
} | ||
|
||
/// Receives a message from the channel. | ||
/// | ||
/// Like [`Receiver::recv`], but uses a cloned `Receiver`. | ||
/// | ||
/// Good for using `Recv` in `Future` impls. | ||
pub fn recv_owned(&self) -> RecvOwned<T> { | ||
RecvOwned::_new(RecvOwnedInner { | ||
receiver: self.clone(), | ||
listener: None, | ||
_pin: PhantomPinned, | ||
}) | ||
} | ||
|
||
Comment on lines
+588
to
+595
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add an example for this function, preferably one that points out where it could be useful. |
||
/// Receives a message from the channel using the blocking strategy. | ||
/// | ||
/// If the channel is empty, this method waits until there is a message. | ||
|
@@ -1201,6 +1214,61 @@ impl<'a, T> EventListenerFuture for RecvInner<'a, T> { | |
} | ||
} | ||
|
||
easy_wrapper! { | ||
/// A future returned by [`Receiver::recv_owned()`]. | ||
#[derive(Debug)] | ||
#[must_use = "futures do nothing unless you `.await` or poll them"] | ||
pub struct RecvOwned<T>(RecvOwnedInner<T> => Result<T, RecvError>); | ||
#[cfg(all(feature = "std", not(target_family = "wasm")))] | ||
pub(crate) wait(); | ||
} | ||
|
||
pin_project! { | ||
#[derive(Debug)] | ||
#[project(!Unpin)] | ||
struct RecvOwnedInner<T> { | ||
// Reference to the receiver. | ||
receiver: Receiver<T>, | ||
|
||
// Listener waiting on the channel. | ||
listener: Option<EventListener>, | ||
|
||
// Keeping this type `!Unpin` enables future optimizations. | ||
#[pin] | ||
_pin: PhantomPinned | ||
} | ||
} | ||
|
||
impl<T> EventListenerFuture for RecvOwnedInner<T> { | ||
type Output = Result<T, RecvError>; | ||
|
||
/// Run this future with the given `Strategy`. | ||
fn poll_with_strategy<'x, S: Strategy<'x>>( | ||
self: Pin<&mut Self>, | ||
strategy: &mut S, | ||
cx: &mut S::Context, | ||
) -> Poll<Result<T, RecvError>> { | ||
let this = self.project(); | ||
|
||
loop { | ||
// Attempt to receive a message. | ||
match this.receiver.try_recv() { | ||
Ok(msg) => return Poll::Ready(Ok(msg)), | ||
Err(TryRecvError::Closed) => return Poll::Ready(Err(RecvError)), | ||
Err(TryRecvError::Empty) => {} | ||
} | ||
|
||
// Receiving failed - now start listening for notifications or wait for one. | ||
if this.listener.is_some() { | ||
// Poll using the given strategy | ||
ready!(S::poll(strategy, &mut *this.listener, cx)); | ||
} else { | ||
*this.listener = Some(this.receiver.channel.recv_ops.listen()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
Comment on lines
+1217
to
+1271
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than duplicating all of this code from struct RecvInner<T, Channel: Borrow<Receiver<T>> { ... } ...then do this: pub struct Recv<'a, T>(RecvInner<T, &'a Receiver<T>>);
pub struct RecvOwned<T>(RecvInner<T, Receiver<T>>); This would prevent duplicating around 250 lines of code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm playing around with this suggestion, but the compiler complains about I'll figure it out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I propose 01fbd7d (it should be possible to fast-forward to that commit if no further adjustments to it are necessary) |
||
#[cfg(feature = "std")] | ||
use std::process::abort; | ||
|
||
|
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.
Avoid using sentence fragments in documentation.
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.
Yes, it could be useful for send.
I'll clean up my doc comments.