diff --git a/proxy/src/lib.rs b/proxy/src/lib.rs index bc3b09f01..c79d6e589 100644 --- a/proxy/src/lib.rs +++ b/proxy/src/lib.rs @@ -76,6 +76,7 @@ mod transparency; mod transport; pub mod timeout; mod tower_fn; // TODO: move to tower-fn +mod rng; use bind::Bind; use connection::BoundPort; diff --git a/proxy/src/outbound.rs b/proxy/src/outbound.rs index cf09175df..f4cc67346 100644 --- a/proxy/src/outbound.rs +++ b/proxy/src/outbound.rs @@ -5,7 +5,6 @@ use std::sync::Arc; use http; use futures::{Async, Poll}; -use rand; use tower_service as tower; use tower_balance::{self, choose, load, Balance}; use tower_buffer::Buffer; @@ -21,6 +20,7 @@ use ctx; use timeout::Timeout; use transparency::h1; use transport::{DnsNameAndPort, Host, HostAndPort}; +use rng::LazyThreadRng; type BindProtocol = bind::BindProtocol, B>; @@ -77,7 +77,7 @@ where type RouteError = bind::BufferSpawnError; type Service = InFlightLimit>, - choose::PowerOfTwoChoices + choose::PowerOfTwoChoices >>>>; fn recognize(&self, req: &Self::Request) -> Option { @@ -153,7 +153,7 @@ where let loaded = tower_balance::load::WithPendingRequests::new(resolve); - let balance = tower_balance::power_of_two_choices(loaded, rand::thread_rng()); + let balance = tower_balance::power_of_two_choices(loaded, LazyThreadRng); // use the same executor as the underlying `Bind` for the `Buffer` and // `Timeout`. diff --git a/proxy/src/rng.rs b/proxy/src/rng.rs new file mode 100644 index 000000000..9f7920d66 --- /dev/null +++ b/proxy/src/rng.rs @@ -0,0 +1,26 @@ +use rand; + +/// An empty type which implements `rand::Rng` by lazily getting the current +/// `thread_rng` when its' called. +/// +/// This can be used in cases where we need a type to be `Send`, but wish to +/// use the thread-local RNG. +#[derive(Copy, Clone, Debug, Default)] +pub struct LazyThreadRng; + +// ===== impl LazyRng ===== + +impl rand::Rng for LazyThreadRng { + fn next_u32(&mut self) -> u32 { + rand::thread_rng().next_u32() + } + + fn next_u64(&mut self) -> u64 { + rand::thread_rng().next_u64() + } + + #[inline] + fn fill_bytes(&mut self, bytes: &mut [u8]) { + rand::thread_rng().fill_bytes(bytes) + } +}