Skip to content

Commit

Permalink
handoff: rename Push->Pusher, Pop->Popper like spsc
Browse files Browse the repository at this point in the history
  • Loading branch information
cbiffle committed Mar 1, 2024
1 parent a603113 commit 97c581b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 27 deletions.
5 changes: 5 additions & 0 deletions RELEASE-NOTES.mkdn
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
porting existing programs, look for uses of the `sleep_*`, `with_*`, and
`PeriodicGate` APIs; they have moved.

- Renamed `spsc` and `handoff` split handle types: `Push` is now `Pusher`, `Pop`
is now `Popper`. (Because their old names sounded like what you'd name the
future type for _completing_ a push or pop, and I felt like that was
misleading.)

- Totally reworked the Mutex API to further improve robustness in the face of
cancellation.
- The basic locking operation `lock` (and its friend `try_lock`) now return a
Expand Down
55 changes: 28 additions & 27 deletions os/src/handoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
//! # Creating and using a `Handoff`
//!
//! Because the `Handoff` itself contains no storage, they're cheap to create on
//! the stack. You then need to `split` then into their `Push` and `Pop` ends --
//! these both _borrow_ the `Handoff`, so you need to keep it around. You can
//! then hand the ends off to other futures. A typical use case looks like this:
//! the stack. You then need to `split` then into their `Pusher` and `Popper`
//! ends -- these both _borrow_ the `Handoff`, so you need to keep it around.
//! You can then hand the ends off to other futures. A typical use case looks
//! like this:
//!
//! ```ignore
//! let mut handoff = Handoff::new();
Expand All @@ -31,9 +32,9 @@
//!
//! # Caveats and alternatives
//!
//! Only one `Push` and `Pop` can exist at a time -- the compiler ensures this.
//! This simplifies the implementation quite a bit, but it means that if you
//! want a multi-party rendezvous this isn't the right tool.
//! Only one `Pusher` and `Popper` can exist at a time -- the compiler ensures
//! this. This simplifies the implementation quite a bit, but it means that if
//! you want a multi-party rendezvous this isn't the right tool.
//!
//! If you would like to be able to push data and go on about your business
//! without waiting for it to be popped, you want a queue, not a handoff. See
Expand All @@ -50,8 +51,8 @@
//!
//! This module is currently the only part of `lilos` that has non-deprecated
//! API that is not strictly cancel-safe. This is often okay, the way handoffs
//! are used (in my code at least), but please read the docs for [`Push::push`]
//! carefully.
//! are used (in my code at least), but please read the docs for
//! [`Pusher::push`] carefully.

use core::cell::Cell;
use core::ptr::NonNull;
Expand All @@ -77,12 +78,12 @@ impl<T> Handoff<T> {
}
}

/// Borrows `self` exclusively and produces `Push` and `Pop` endpoints. The
/// endpoints are guaranteed to be unique, since they can't be cloned and
/// you can't call `split` to make new ones until both are
/// Borrows `self` exclusively and produces `Pusher` and `Popper` endpoints.
/// The endpoints are guaranteed to be unique, since they can't be cloned
/// and you can't call `split` to make new ones until both are
/// dropped/forgotten.
pub fn split(&mut self) -> (Push<'_, T>, Pop<'_, T>) {
(Push(self), Pop(self))
pub fn split(&mut self) -> (Pusher<'_, T>, Popper<'_, T>) {
(Pusher(self), Popper(self))
}
}

Expand Down Expand Up @@ -150,14 +151,14 @@ impl<T> Clone for State<T> {
}

/// Push endpoint for a `Handoff<T>`. Holding this allows you to offer a single
/// item at a time to whoever's holding the `Pop` side.
pub struct Push<'a, T>(&'a Handoff<T>);
/// item at a time to whoever's holding the `Popper` side.
pub struct Pusher<'a, T>(&'a Handoff<T>);

impl<T> Push<'_, T> {
impl<T> Pusher<'_, T> {
/// Offers `value` to our peer, if they are waiting to receive it.
///
/// If someone is blocked on the `Pop` side, `value` is transferred to them,
/// they are unblocked, and this returns `Ok(())`.
/// If someone is blocked on the `Popper` side, `value` is transferred to
/// them, they are unblocked, and this returns `Ok(())`.
///
/// Otherwise, it returns `Err(value)`, giving `value` back to you.
pub fn try_push(&mut self, value: T) -> Result<(), T> {
Expand Down Expand Up @@ -250,18 +251,18 @@ impl<T> Push<'_, T> {
}

/// Implement Debug by hand so it doesn't require T: Debug.
impl<T> core::fmt::Debug for Push<'_, T> {
impl<T> core::fmt::Debug for Pusher<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Push").field(&self.0).finish()
f.debug_tuple("Pusher").field(&self.0).finish()
}
}

/// Pop endpoint for a `Handoff<T>`. Holding this allows you to take a single
/// item at a time from whoever's holding the `Push` side.
pub struct Pop<'a, T>(&'a Handoff<T>);
/// item at a time from whoever's holding the `Pusher` side.
pub struct Popper<'a, T>(&'a Handoff<T>);

impl<T> Pop<'_, T> {
/// Takes data from the `Push` peer if it's waiting.
impl<T> Popper<'_, T> {
/// Takes data from the `Pusher` peer if it's waiting.
///
/// If the peer is blocked offering us data, this unblocks them and returns
/// `Some(value)`.
Expand Down Expand Up @@ -292,7 +293,7 @@ impl<T> Pop<'_, T> {
/// **Cancel Safety:** Strict.
///
/// If this is dropped before it resolves, no data will be lost: we have
/// either taken data from the `Push` side and resolved, or we have not
/// either taken data from the `Pusher` side and resolved, or we have not
/// taken data.
pub async fn pop(&mut self) -> T {
let mut guard = scopeguard::guard(None, |v| {
Expand Down Expand Up @@ -352,8 +353,8 @@ impl<T> Pop<'_, T> {
}

/// Implement Debug by hand so it doesn't require T: Debug.
impl<T> core::fmt::Debug for Pop<'_, T> {
impl<T> core::fmt::Debug for Popper<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Pop").field(&self.0).finish()
f.debug_tuple("Popper").field(&self.0).finish()
}
}

0 comments on commit 97c581b

Please sign in to comment.