Skip to content

Commit 27bab37

Browse files
committed
Remove rand dependency by using our own PRNG
1 parent 62894c6 commit 27bab37

File tree

7 files changed

+71
-17
lines changed

7 files changed

+71
-17
lines changed

.travis.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ matrix:
112112
- cargo build --manifest-path futures/Cargo.toml
113113
--target thumbv6m-none-eabi
114114
--no-default-features
115-
--features unstable,alloc,cfg-target-has-atomic
115+
--features unstable,cfg-target-has-atomic,alloc
116+
- cargo build --manifest-path futures/Cargo.toml
117+
--target thumbv6m-none-eabi
118+
--no-default-features
119+
--features unstable,cfg-target-has-atomic,async-await
116120

117121
- name: cargo build --target=thumbv7m-none-eabi
118122
rust: nightly
@@ -127,6 +131,10 @@ matrix:
127131
--target thumbv7m-none-eabi
128132
--no-default-features
129133
--features alloc
134+
- cargo build --manifest-path futures/Cargo.toml
135+
--target thumbv7m-none-eabi
136+
--no-default-features
137+
--features async-await
130138

131139
- name: cargo check (futures-util)
132140
rust: nightly

futures-select-macro/src/lib.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ pub fn select(input: TokenStream) -> TokenStream {
149149
let parsed = syn::parse_macro_input!(input as Select);
150150

151151
let futures_crate: syn::Path = parsed.futures_crate_path.unwrap_or_else(|| parse_quote!(::futures_util));
152-
let rand_crate: syn::Path = parse_quote!(#futures_crate::rand_reexport);
153152

154153
// should be def_site, but that's unstable
155154
let span = Span::call_site();
@@ -265,10 +264,7 @@ pub fn select(input: TokenStream) -> TokenStream {
265264
#( #poll_functions )*
266265

267266
let mut __select_arr = [#( #variant_names ),*];
268-
<[_] as #rand_crate::SliceRandom>::shuffle(
269-
&mut __select_arr,
270-
&mut #rand_crate::thread_rng(),
271-
);
267+
#futures_crate::async_await::shuffle(&mut __select_arr);
272268
for poller in &mut __select_arr {
273269
let poller: &mut &mut dyn FnMut(
274270
&mut #futures_crate::task::Context<'_>

futures-util/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ sink = ["futures-sink-preview"]
2525
io = ["std", "futures-io-preview", "memchr"]
2626
channel = ["std", "futures-channel-preview"]
2727
join-macro = ["async-await", "futures-join-macro-preview", "proc-macro-hack", "proc-macro-nested"]
28-
select-macro = ["async-await", "futures-select-macro-preview", "proc-macro-hack", "proc-macro-nested", "rand"]
28+
select-macro = ["async-await", "futures-select-macro-preview", "proc-macro-hack", "proc-macro-nested"]
2929

3030
# Unstable features
3131
# These features are outside of the normal semver guarantees and require the
@@ -43,7 +43,6 @@ futures-join-macro-preview = { path = "../futures-join-macro", version = "=0.3.0
4343
futures-select-macro-preview = { path = "../futures-select-macro", version = "=0.3.0-alpha.18", default-features = false, optional = true }
4444
proc-macro-hack = { version = "0.5.9", optional = true }
4545
proc-macro-nested = { version = "0.1.2", optional = true }
46-
rand = { version = "0.7.0", optional = true }
4746
slab = { version = "0.4", optional = true }
4847
memchr = { version = "2.2", optional = true }
4948
futures_01 = { version = "0.1.25", optional = true, package = "futures" }

futures-util/src/async_await/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ mod select_mod;
3131
#[cfg(feature = "select-macro")]
3232
pub use self::select_mod::*;
3333

34+
#[cfg(feature = "select-macro")]
35+
mod random;
36+
#[cfg(feature = "select-macro")]
37+
pub use self::random::*;
38+
3439
#[doc(hidden)]
3540
#[inline(always)]
3641
pub fn assert_unpin<T: Unpin>(_: &T) {}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::{
2+
cell::Cell,
3+
collections::hash_map::DefaultHasher,
4+
hash::Hasher,
5+
num::Wrapping,
6+
sync::atomic::{AtomicUsize, Ordering},
7+
};
8+
9+
// Based on [Fisher–Yates shuffle]
10+
//
11+
// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
12+
#[doc(hidden)]
13+
pub fn shuffle<T>(slice: &mut [T]) {
14+
for i in (1..slice.len()).rev() {
15+
slice.swap(i, gen_index(i + 1));
16+
}
17+
}
18+
19+
/// Return a value from `0..n`.
20+
fn gen_index(n: usize) -> usize {
21+
(random() % n as u64) as usize
22+
}
23+
24+
/// Pseudorandom number generator based on [xorshift*].
25+
///
26+
/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift*
27+
fn random() -> u64 {
28+
thread_local! {
29+
static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(prng_seed()));
30+
}
31+
32+
fn prng_seed() -> u64 {
33+
static COUNTER: AtomicUsize = AtomicUsize::new(0);
34+
35+
// Any non-zero seed will do
36+
let mut seed = 0;
37+
while seed == 0 {
38+
let mut hasher = DefaultHasher::new();
39+
hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed));
40+
seed = hasher.finish();
41+
}
42+
seed
43+
}
44+
45+
RNG.with(|rng| {
46+
let mut x = rng.get();
47+
debug_assert_ne!(x.0, 0);
48+
x ^= x >> 12;
49+
x ^= x << 25;
50+
x ^= x >> 27;
51+
rng.set(x);
52+
x.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
53+
})
54+
}

futures-util/src/lib.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,6 @@ pub mod async_await;
3939
#[doc(hidden)]
4040
pub use self::async_await::*;
4141

42-
#[cfg(feature = "std")]
43-
#[cfg(feature = "select-macro")]
44-
#[doc(hidden)]
45-
pub mod rand_reexport { // used by select!
46-
#[doc(hidden)]
47-
pub use rand::{prelude::SliceRandom, thread_rng};
48-
}
49-
5042
#[doc(hidden)]
5143
pub use futures_core::core_reexport;
5244

futures/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ pub mod never {
527527
#[cfg(feature = "std")]
528528
#[cfg(feature = "async-await")]
529529
#[doc(hidden)]
530-
pub use futures_util::rand_reexport;
530+
pub use futures_util::async_await;
531531

532532
#[cfg(feature = "std")]
533533
#[cfg(feature = "async-await")]

0 commit comments

Comments
 (0)