Skip to content

Commit

Permalink
refactor: Move RaceBiased to separate module
Browse files Browse the repository at this point in the history
  • Loading branch information
cmleinz committed Oct 14, 2024
1 parent 13e2d50 commit b5b5263
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 80 deletions.
5 changes: 4 additions & 1 deletion src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ impl<A> Context<A> {
///
/// A common pattern is to spawn the executor onto an async runtime like tokio.
///
/// ```ignore
/// ```no_run
/// # use black_box::*;
/// # struct MyActor;
/// # impl Actor for MyActor {}
/// let my_actor = MyActor;
/// let (executor, addr) = Executor::new(my_actor);
///
Expand Down
81 changes: 2 additions & 79 deletions src/futures.rs
Original file line number Diff line number Diff line change
@@ -1,80 +1,3 @@
use std::{future::Future, task::Poll};
mod race;

use pin_project_lite::pin_project;

/// Race two futures against one another, favoring the first future over the second
pub fn race_biased<F1, F2>(first: F1, second: F2) -> RaceBiased<F1, F2> {
RaceBiased { first, second }
}

pin_project! {
pub struct RaceBiased<F1, F2> {
#[pin]
first: F1,
#[pin]
second: F2,
}
}

impl<F1, F2, T> Future for RaceBiased<F1, F2>
where
F1: Future<Output = T>,
F2: Future<Output = T>,
{
type Output = T;

fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let this = self.project();

if let Poll::Ready(val) = this.first.poll(cx) {
Poll::Ready(val)
} else if let Poll::Ready(val) = this.second.poll(cx) {
Poll::Ready(val)
} else {
Poll::Pending
}
}
}

#[cfg(test)]
mod tests {
use std::time::Duration;

use super::*;

#[tokio::test]
async fn race_biased_on_ready() {
let first = std::future::ready(true);
let second = std::future::ready(false);
let result = race_biased(first, second).await;
assert!(result);
}

#[tokio::test]
async fn race_biased_on_not_ready() {
let first = async {
tokio::time::sleep(Duration::from_millis(250)).await;
false
};
let second = async {
tokio::time::sleep(Duration::from_millis(100)).await;
true
};
let result = race_biased(first, second).await;
assert!(result);
}

#[tokio::test]
async fn race_biased_on_one_ready() {
let first = async {
tokio::time::sleep(Duration::from_millis(250)).await;
false
};
let second = std::future::ready(true);
let result = race_biased(first, second).await;
assert!(result);
}
}
pub use race::race_biased;
80 changes: 80 additions & 0 deletions src/futures/race.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::{future::Future, task::Poll};

use pin_project_lite::pin_project;

/// Race two futures against one another, favoring the first future over the second
pub fn race_biased<F1, F2>(first: F1, second: F2) -> RaceBiased<F1, F2> {
RaceBiased { first, second }
}

pin_project! {
pub struct RaceBiased<F1, F2> {
#[pin]
first: F1,
#[pin]
second: F2,
}
}

impl<F1, F2, T> Future for RaceBiased<F1, F2>
where
F1: Future<Output = T>,
F2: Future<Output = T>,
{
type Output = T;

fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let this = self.project();

if let Poll::Ready(val) = this.first.poll(cx) {
Poll::Ready(val)
} else if let Poll::Ready(val) = this.second.poll(cx) {
Poll::Ready(val)
} else {
Poll::Pending
}
}
}

#[cfg(test)]
mod tests {
use std::time::Duration;

use super::*;

#[tokio::test]
async fn race_biased_on_ready() {
let first = std::future::ready(true);
let second = std::future::ready(false);
let result = race_biased(first, second).await;
assert!(result);
}

#[tokio::test]
async fn race_biased_on_not_ready() {
let first = async {
tokio::time::sleep(Duration::from_millis(100)).await;
false
};
let second = async {
tokio::time::sleep(Duration::from_millis(25)).await;
true
};
let result = race_biased(first, second).await;
assert!(result);
}

#[tokio::test]
async fn race_biased_on_one_ready() {
let first = async {
tokio::time::sleep(Duration::from_millis(250)).await;
false
};
let second = std::future::ready(true);
let result = race_biased(first, second).await;
assert!(result);
}
}

0 comments on commit b5b5263

Please sign in to comment.