Skip to content

Commit

Permalink
remove rand dependency, use internal prng
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaeroxe committed Aug 14, 2023
1 parent 1be1a61 commit 714f217
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 41 deletions.
4 changes: 1 addition & 3 deletions futures-util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ Common utilities and extension traits for the futures-rs library.

[features]
default = ["std", "async-await", "async-await-macro"]
std = ["alloc", "futures-core/std", "futures-task/std", "rand/std", "rand/std_rng", "slab"]
getrandom = ["rand/getrandom"]
std = ["alloc", "futures-core/std", "futures-task/std", "slab"]
alloc = ["futures-core/alloc", "futures-task/alloc"]
async-await = []
async-await-macro = ["async-await", "futures-macro"]
Expand Down Expand Up @@ -44,7 +43,6 @@ futures_01 = { version = "0.1.25", optional = true, package = "futures" }
tokio-io = { version = "0.1.9", optional = true }
pin-utils = "0.1.0"
pin-project-lite = "0.2.6"
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }

[dev-dependencies]
futures = { path = "../futures", features = ["async-await", "thread-pool"] }
Expand Down
2 changes: 0 additions & 2 deletions futures-util/src/async_await/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ mod stream_select_mod;
pub use self::stream_select_mod::*;

#[cfg(feature = "std")]
#[cfg(feature = "async-await-macro")]
mod random;
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
#[cfg(feature = "std")]
#[cfg(feature = "async-await-macro")]
pub use self::random::*;

#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion futures-util/src/async_await/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub fn shuffle<T>(slice: &mut [T]) {
}

/// Return a value from `0..n`.
fn gen_index(n: usize) -> usize {
pub(crate) fn gen_index(n: usize) -> usize {
(random() % n as u64) as usize
}

Expand Down
14 changes: 8 additions & 6 deletions futures-util/src/future/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ use crate::future::{Either, FutureExt};
use core::pin::Pin;
use futures_core::future::{FusedFuture, Future};
use futures_core::task::{Context, Poll};
use rand::rngs::SmallRng;
use rand::Rng;

/// Future for the [`select()`] function.
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Select<A, B> {
inner: Option<(A, B)>,
rng: SmallRng,
}

impl<A: Unpin, B: Unpin> Unpin for Select<A, B> {}
Expand Down Expand Up @@ -94,7 +91,6 @@ where
{
assert_future::<Either<(A::Output, B), (B::Output, A)>, _>(Select {
inner: Some((future1, future2)),
rng: crate::gen_rng(),
})
}

Expand All @@ -116,7 +112,6 @@ where
}
}

let a_polls_first = self.rng.gen::<bool>();
let (a, b) = self.inner.as_mut().expect("cannot poll Select twice");

macro_rules! poll_wrap {
Expand All @@ -127,13 +122,20 @@ where
};
}

if a_polls_first {
#[cfg(feature = "std")]
if crate::gen_index(2) == 0 {
poll_wrap!(a, unwrap_option(self.inner.take()).1, Either::Left);
poll_wrap!(b, unwrap_option(self.inner.take()).0, Either::Right);
} else {
poll_wrap!(b, unwrap_option(self.inner.take()).0, Either::Right);
poll_wrap!(a, unwrap_option(self.inner.take()).1, Either::Left);
}

#[cfg(not(feature = "std"))]
{
poll_wrap!(a, unwrap_option(self.inner.take()).1, Either::Left);
poll_wrap!(b, unwrap_option(self.inner.take()).0, Either::Right);
}
Poll::Pending
}
}
Expand Down
12 changes: 5 additions & 7 deletions futures-util/src/future/select_ok.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ use core::mem;
use core::pin::Pin;
use futures_core::future::{Future, TryFuture};
use futures_core::task::{Context, Poll};
use rand::prelude::SliceRandom;
use rand::rngs::SmallRng;

/// Future for the [`select_ok`] function.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct SelectOk<Fut> {
inner: Vec<Fut>,
rng: SmallRng,
}

impl<Fut: Unpin> Unpin for SelectOk<Fut> {}
Expand Down Expand Up @@ -48,7 +45,7 @@ where
I: IntoIterator,
I::Item: TryFuture + Unpin,
{
let ret = SelectOk { inner: iter.into_iter().collect(), rng: crate::gen_rng() };
let ret = SelectOk { inner: iter.into_iter().collect() };
assert!(!ret.inner.is_empty(), "iterator provided to select_ok was empty");
assert_future::<
Result<(<I::Item as TryFuture>::Ok, Vec<I::Item>), <I::Item as TryFuture>::Error>,
Expand All @@ -60,8 +57,9 @@ impl<Fut: TryFuture + Unpin> Future for SelectOk<Fut> {
type Output = Result<(Fut::Ok, Vec<Fut>), Fut::Error>;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Self { inner, rng } = &mut *self;
inner.shuffle(rng);
let Self { inner } = &mut *self;
#[cfg(feature = "std")]
crate::shuffle(inner);
// loop until we've either exhausted all errors, a success was hit, or nothing is ready
loop {
let item = inner.iter_mut().enumerate().find_map(|(i, f)| match f.try_poll_unpin(cx) {
Expand All @@ -74,7 +72,7 @@ impl<Fut: TryFuture + Unpin> Future for SelectOk<Fut> {
drop(inner.remove(idx));
match res {
Ok(e) => {
let rest = mem::take(&mut self.inner);
let rest = mem::take(inner);
return Poll::Ready(Ok((e, rest)));
}
Err(e) => {
Expand Down
13 changes: 8 additions & 5 deletions futures-util/src/future/try_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ use crate::future::{Either, TryFutureExt};
use core::pin::Pin;
use futures_core::future::{Future, TryFuture};
use futures_core::task::{Context, Poll};
use rand::rngs::SmallRng;
use rand::Rng;

/// Future for the [`try_select()`] function.
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct TrySelect<A, B> {
inner: Option<(A, B)>,
rng: SmallRng,
}

impl<A: Unpin, B: Unpin> Unpin for TrySelect<A, B> {}
Expand Down Expand Up @@ -63,7 +60,6 @@ where
{
super::assert_future::<Result<EitherOk<A, B>, EitherErr<A, B>>, _>(TrySelect {
inner: Some((future1, future2)),
rng: crate::gen_rng(),
})
}

Expand Down Expand Up @@ -92,10 +88,17 @@ where
}
};
}
if self.rng.gen::<bool>() {

#[cfg(feature = "std")]
if crate::gen_index(2) == 0 {
poll_wrap!(a, b, Either::Left, Either::Right)
} else {
poll_wrap!(b, a, Either::Right, Either::Left)
}

#[cfg(not(feature = "std"))]
{
poll_wrap!(a, b, Either::Left, Either::Right)
}
}
}
17 changes: 0 additions & 17 deletions futures-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ extern crate alloc;
// Macro re-exports
pub use futures_core::ready;
pub use pin_utils::pin_mut;
use rand::rngs::SmallRng;
use rand::SeedableRng;

#[cfg(feature = "async-await")]
#[macro_use]
Expand Down Expand Up @@ -338,18 +336,3 @@ mod abortable;

mod fns;
mod unfold_state;

fn gen_rng() -> SmallRng {
#[cfg(feature = "std")]
{
SmallRng::from_rng(rand::thread_rng()).expect("generating SmallRng via thread_rng failed")
}
#[cfg(all(feature = "getrandom", not(feature = "std")))]
{
SmallRng::from_entropy()
}
#[cfg(not(any(feature = "getrandom", feature = "std")))]
{
SmallRng::seed_from_u64(0)
}
}

0 comments on commit 714f217

Please sign in to comment.