mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +02:00
chore: apply rustfmt to all crates (#917)
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
#![feature(test)]
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate tokio_threadpool;
|
||||
extern crate futures;
|
||||
extern crate futures_cpupool;
|
||||
extern crate num_cpus;
|
||||
extern crate test;
|
||||
extern crate tokio_threadpool;
|
||||
|
||||
const NUM_SPAWN: usize = 10_000;
|
||||
const NUM_YIELD: usize = 1_000;
|
||||
@@ -13,12 +13,12 @@ const TASKS_PER_CPU: usize = 50;
|
||||
|
||||
mod threadpool {
|
||||
use futures::{future, task, Async};
|
||||
use tokio_threadpool::*;
|
||||
use num_cpus;
|
||||
use test;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use test;
|
||||
use tokio_threadpool::*;
|
||||
|
||||
#[bench]
|
||||
fn spawn_many(b: &mut test::Bencher) {
|
||||
@@ -90,14 +90,14 @@ mod threadpool {
|
||||
// See rust-lang-nursery/futures-rs#617
|
||||
//
|
||||
mod cpupool {
|
||||
use futures::{task, Async};
|
||||
use futures::future::{self, Executor};
|
||||
use futures::{task, Async};
|
||||
use futures_cpupool::*;
|
||||
use num_cpus;
|
||||
use test;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use test;
|
||||
|
||||
#[bench]
|
||||
fn spawn_many(b: &mut test::Bencher) {
|
||||
@@ -119,7 +119,9 @@ mod cpupool {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})).ok().unwrap();
|
||||
}))
|
||||
.ok()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let _ = rx.recv().unwrap();
|
||||
@@ -151,7 +153,9 @@ mod cpupool {
|
||||
// Not ready
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
})).ok().unwrap();
|
||||
}))
|
||||
.ok()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
for _ in 0..tasks {
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
extern crate futures;
|
||||
extern crate rand;
|
||||
extern crate tokio_threadpool;
|
||||
extern crate threadpool;
|
||||
extern crate test;
|
||||
extern crate threadpool;
|
||||
extern crate tokio_threadpool;
|
||||
|
||||
const ITER: usize = 1_000;
|
||||
|
||||
@@ -13,14 +13,11 @@ mod blocking {
|
||||
use super::*;
|
||||
|
||||
use futures::future::*;
|
||||
use tokio_threadpool::{Builder, blocking};
|
||||
use tokio_threadpool::{blocking, Builder};
|
||||
|
||||
#[bench]
|
||||
fn cpu_bound(b: &mut test::Bencher) {
|
||||
let pool = Builder::new()
|
||||
.pool_size(2)
|
||||
.max_blocking(20)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(2).max_blocking(20).build();
|
||||
|
||||
b.iter(|| {
|
||||
let count_down = Arc::new(CountDown::new(::ITER));
|
||||
@@ -29,17 +26,12 @@ mod blocking {
|
||||
let count_down = count_down.clone();
|
||||
|
||||
pool.spawn(lazy(move || {
|
||||
poll_fn(|| {
|
||||
blocking(|| {
|
||||
perform_complex_computation()
|
||||
poll_fn(|| blocking(|| perform_complex_computation()).map_err(|_| panic!()))
|
||||
.and_then(move |_| {
|
||||
// Do something with the value
|
||||
count_down.dec();
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
.and_then(move |_| {
|
||||
// Do something with the value
|
||||
count_down.dec();
|
||||
Ok(())
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -57,10 +49,7 @@ mod message_passing {
|
||||
|
||||
#[bench]
|
||||
fn cpu_bound(b: &mut test::Bencher) {
|
||||
let pool = Builder::new()
|
||||
.pool_size(2)
|
||||
.max_blocking(20)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(2).max_blocking(20).build();
|
||||
|
||||
let blocking = threadpool::ThreadPool::new(20);
|
||||
|
||||
@@ -85,7 +74,8 @@ mod message_passing {
|
||||
rx.and_then(move |_| {
|
||||
count_down.dec();
|
||||
Ok(())
|
||||
}).map_err(|_| panic!())
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -104,9 +94,9 @@ fn perform_complex_computation() -> usize {
|
||||
|
||||
// Util for waiting until the tasks complete
|
||||
|
||||
use std::sync::*;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::*;
|
||||
use std::sync::*;
|
||||
|
||||
struct CountDown {
|
||||
rem: AtomicUsize,
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#![feature(test)]
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate tokio_threadpool;
|
||||
extern crate futures;
|
||||
extern crate futures_cpupool;
|
||||
extern crate num_cpus;
|
||||
extern crate test;
|
||||
extern crate tokio_threadpool;
|
||||
|
||||
const ITER: usize = 20_000;
|
||||
|
||||
mod us {
|
||||
use tokio_threadpool::*;
|
||||
use futures::future;
|
||||
use test;
|
||||
use std::sync::mpsc;
|
||||
use test;
|
||||
use tokio_threadpool::*;
|
||||
|
||||
#[bench]
|
||||
fn chained_spawn(b: &mut test::Bencher) {
|
||||
@@ -24,10 +24,12 @@ mod us {
|
||||
res_tx.send(()).unwrap();
|
||||
} else {
|
||||
let pool_tx2 = pool_tx.clone();
|
||||
pool_tx.spawn(future::lazy(move || {
|
||||
spawn(pool_tx2, res_tx, n - 1);
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
pool_tx
|
||||
.spawn(future::lazy(move || {
|
||||
spawn(pool_tx2, res_tx, n - 1);
|
||||
Ok(())
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +46,8 @@ mod cpupool {
|
||||
use futures::future::{self, Executor};
|
||||
use futures_cpupool::*;
|
||||
use num_cpus;
|
||||
use test;
|
||||
use std::sync::mpsc;
|
||||
use test;
|
||||
|
||||
#[bench]
|
||||
fn chained_spawn(b: &mut test::Bencher) {
|
||||
@@ -59,7 +61,9 @@ mod cpupool {
|
||||
pool.execute(future::lazy(move || {
|
||||
spawn(pool2, res_tx, n - 1);
|
||||
Ok(())
|
||||
})).ok().unwrap();
|
||||
}))
|
||||
.ok()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
extern crate tokio_threadpool;
|
||||
extern crate env_logger;
|
||||
|
||||
use tokio_threadpool::*;
|
||||
use futures::future::{self, Executor};
|
||||
use tokio_threadpool::*;
|
||||
|
||||
use std::sync::mpsc;
|
||||
|
||||
@@ -22,7 +22,9 @@ fn chained_spawn() {
|
||||
tx.execute(future::lazy(move || {
|
||||
spawn(tx2, res_tx, n - 1);
|
||||
Ok(())
|
||||
})).ok().unwrap();
|
||||
}))
|
||||
.ok()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
extern crate tokio_threadpool;
|
||||
extern crate env_logger;
|
||||
|
||||
use tokio_threadpool::*;
|
||||
use futures::*;
|
||||
use futures::sync::oneshot;
|
||||
use futures::*;
|
||||
use tokio_threadpool::*;
|
||||
|
||||
pub fn main() {
|
||||
let _ = ::env_logger::init();
|
||||
@@ -12,10 +12,13 @@ pub fn main() {
|
||||
let pool = ThreadPool::new();
|
||||
let tx = pool.sender().clone();
|
||||
|
||||
let res = oneshot::spawn(future::lazy(|| {
|
||||
println!("Running on the pool");
|
||||
Ok::<_, ()>("complete")
|
||||
}), &tx);
|
||||
let res = oneshot::spawn(
|
||||
future::lazy(|| {
|
||||
println!("Running on the pool");
|
||||
Ok::<_, ()>("complete")
|
||||
}),
|
||||
&tx,
|
||||
);
|
||||
|
||||
println!("Result: {:?}", res.wait());
|
||||
}
|
||||
|
||||
@@ -122,7 +122,8 @@ pub struct BlockingError {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn blocking<F, T>(f: F) -> Poll<T, BlockingError>
|
||||
where F: FnOnce() -> T,
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let res = Worker::with_current(|worker| {
|
||||
let worker = match worker {
|
||||
@@ -148,8 +149,7 @@ where F: FnOnce() -> T,
|
||||
// back ownership of the worker if the worker handoff didn't complete yet.
|
||||
Worker::with_current(|worker| {
|
||||
// Worker must be set since it was above.
|
||||
worker.unwrap()
|
||||
.transition_from_blocking();
|
||||
worker.unwrap().transition_from_blocking();
|
||||
});
|
||||
|
||||
// Return the result
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
use callback::Callback;
|
||||
use config::{Config, MAX_WORKERS};
|
||||
use park::{BoxPark, BoxedPark, DefaultPark};
|
||||
use shutdown::ShutdownTrigger;
|
||||
use pool::{Pool, MAX_BACKUP};
|
||||
use shutdown::ShutdownTrigger;
|
||||
use thread_pool::ThreadPool;
|
||||
use worker::{self, Worker, WorkerId};
|
||||
|
||||
use std::cmp::max;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::cmp::max;
|
||||
|
||||
use crossbeam_deque::Injector;
|
||||
use num_cpus;
|
||||
use tokio_executor::Enter;
|
||||
use tokio_executor::park::Park;
|
||||
use tokio_executor::Enter;
|
||||
|
||||
/// Builds a thread pool with custom configuration values.
|
||||
///
|
||||
@@ -93,10 +93,8 @@ impl Builder {
|
||||
pub fn new() -> Builder {
|
||||
let num_cpus = max(1, num_cpus::get());
|
||||
|
||||
let new_park = Box::new(|_: &WorkerId| {
|
||||
Box::new(BoxedPark::new(DefaultPark::new()))
|
||||
as BoxPark
|
||||
});
|
||||
let new_park =
|
||||
Box::new(|_: &WorkerId| Box::new(BoxedPark::new(DefaultPark::new())) as BoxPark);
|
||||
|
||||
Builder {
|
||||
pool_size: num_cpus,
|
||||
@@ -280,7 +278,8 @@ impl Builder {
|
||||
///
|
||||
/// [`Worker::run`]: struct.Worker.html#method.run
|
||||
pub fn around_worker<F>(&mut self, f: F) -> &mut Self
|
||||
where F: Fn(&Worker, &mut Enter) + Send + Sync + 'static
|
||||
where
|
||||
F: Fn(&Worker, &mut Enter) + Send + Sync + 'static,
|
||||
{
|
||||
self.config.around_worker = Some(Callback::new(f));
|
||||
self
|
||||
@@ -307,7 +306,8 @@ impl Builder {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn after_start<F>(&mut self, f: F) -> &mut Self
|
||||
where F: Fn() + Send + Sync + 'static
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
self.config.after_start = Some(Arc::new(f));
|
||||
self
|
||||
@@ -333,7 +333,8 @@ impl Builder {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn before_stop<F>(&mut self, f: F) -> &mut Self
|
||||
where F: Fn() + Send + Sync + 'static
|
||||
where
|
||||
F: Fn() + Send + Sync + 'static,
|
||||
{
|
||||
self.config.before_stop = Some(Arc::new(f));
|
||||
self
|
||||
@@ -369,13 +370,12 @@ impl Builder {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn custom_park<F, P>(&mut self, f: F) -> &mut Self
|
||||
where F: Fn(&WorkerId) -> P + 'static,
|
||||
P: Park + Send + 'static,
|
||||
P::Error: Error,
|
||||
where
|
||||
F: Fn(&WorkerId) -> P + 'static,
|
||||
P: Park + Send + 'static,
|
||||
P::Error: Error,
|
||||
{
|
||||
self.new_park = Box::new(move |id| {
|
||||
Box::new(BoxedPark::new(f(id)))
|
||||
});
|
||||
self.new_park = Box::new(move |id| Box::new(BoxedPark::new(f(id))));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ pub(crate) struct Callback {
|
||||
|
||||
impl Callback {
|
||||
pub fn new<F>(f: F) -> Self
|
||||
where F: Fn(&Worker, &mut Enter) + Send + Sync + 'static
|
||||
where
|
||||
F: Fn(&Worker, &mut Enter) + Send + Sync + 'static,
|
||||
{
|
||||
Callback { f: Arc::new(f) }
|
||||
}
|
||||
|
||||
@@ -159,5 +159,5 @@ pub use blocking::{blocking, BlockingError};
|
||||
pub use builder::Builder;
|
||||
pub use sender::Sender;
|
||||
pub use shutdown::Shutdown;
|
||||
pub use thread_pool::{ThreadPool, SpawnHandle};
|
||||
pub use thread_pool::{SpawnHandle, ThreadPool};
|
||||
pub use worker::{Worker, WorkerId};
|
||||
|
||||
@@ -15,7 +15,8 @@ impl<T> BoxedPark<T> {
|
||||
}
|
||||
|
||||
impl<T: Park + Send> Park for BoxedPark<T>
|
||||
where T::Error: Error,
|
||||
where
|
||||
T::Error: Error,
|
||||
{
|
||||
type Unpark = BoxUnpark;
|
||||
type Error = ();
|
||||
@@ -25,16 +26,20 @@ where T::Error: Error,
|
||||
}
|
||||
|
||||
fn park(&mut self) -> Result<(), Self::Error> {
|
||||
self.0.park()
|
||||
.map_err(|e| {
|
||||
warn!("calling `park` on worker thread errored -- shutting down thread: {}", e);
|
||||
})
|
||||
self.0.park().map_err(|e| {
|
||||
warn!(
|
||||
"calling `park` on worker thread errored -- shutting down thread: {}",
|
||||
e
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
|
||||
self.0.park_timeout(duration)
|
||||
.map_err(|e| {
|
||||
warn!("calling `park` on worker thread errored -- shutting down thread: {}", e);
|
||||
})
|
||||
self.0.park_timeout(duration).map_err(|e| {
|
||||
warn!(
|
||||
"calling `park` on worker thread errored -- shutting down thread: {}",
|
||||
e
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use park::DefaultPark;
|
||||
use worker::{WorkerId};
|
||||
use worker::WorkerId;
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fmt;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::{self, Acquire, AcqRel, Relaxed};
|
||||
use std::sync::atomic::Ordering::{self, AcqRel, Acquire, Relaxed};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
/// State associated with a thread in the thread pool.
|
||||
@@ -100,9 +100,11 @@ impl Backup {
|
||||
});
|
||||
|
||||
// The handoff value is equal to `worker_id`
|
||||
debug_assert_eq!(unsafe { (*self.handoff.get()).as_ref() }, Some(worker_id));
|
||||
debug_assert_eq!(unsafe { (*self.handoff.get()).as_ref() }, Some(worker_id));
|
||||
|
||||
unsafe { *self.handoff.get() = None; }
|
||||
unsafe {
|
||||
*self.handoff.get() = None;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
@@ -167,10 +169,7 @@ impl Backup {
|
||||
return Handoff::Terminated;
|
||||
}
|
||||
|
||||
let worker_id = unsafe {
|
||||
(*self.handoff.get()).take()
|
||||
.expect("no worker handoff")
|
||||
};
|
||||
let worker_id = unsafe { (*self.handoff.get()).take().expect("no worker handoff") };
|
||||
return Handoff::Worker(worker_id);
|
||||
}
|
||||
|
||||
@@ -192,10 +191,10 @@ impl Backup {
|
||||
let mut next = state;
|
||||
next.unset_running();
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(),
|
||||
next.into(),
|
||||
AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
debug_assert!(!next.is_running());
|
||||
@@ -226,7 +225,9 @@ impl Backup {
|
||||
|
||||
#[inline]
|
||||
pub fn set_next_sleeper(&self, val: BackupId) {
|
||||
unsafe { *self.next_sleeper.get() = val; }
|
||||
unsafe {
|
||||
*self.next_sleeper.get() = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,8 +272,9 @@ impl State {
|
||||
next.set_running();
|
||||
next.unset_pushed();
|
||||
|
||||
let actual = state.compare_and_swap(
|
||||
curr.into(), next.into(), AcqRel).into();
|
||||
let actual = state
|
||||
.compare_and_swap(curr.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == curr {
|
||||
return curr;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use pool::{Backup, BackupId};
|
||||
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::{Acquire, AcqRel};
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct BackupStack {
|
||||
@@ -65,8 +65,10 @@ impl BackupStack {
|
||||
entries[id.0].set_next_sleeper(head);
|
||||
next.set_head(id);
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if state == actual {
|
||||
return Ok(());
|
||||
@@ -110,8 +112,10 @@ impl BackupStack {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual != state {
|
||||
state = actual;
|
||||
@@ -138,8 +142,10 @@ impl BackupStack {
|
||||
next.set_head(next_head);
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
debug_assert!(entries[head.0].is_pushed());
|
||||
|
||||
@@ -4,11 +4,7 @@ mod state;
|
||||
|
||||
pub(crate) use self::backup::{Backup, BackupId};
|
||||
pub(crate) use self::backup_stack::MAX_BACKUP;
|
||||
pub(crate) use self::state::{
|
||||
State,
|
||||
Lifecycle,
|
||||
MAX_FUTURES,
|
||||
};
|
||||
pub(crate) use self::state::{Lifecycle, State, MAX_FUTURES};
|
||||
|
||||
use self::backup::Handoff;
|
||||
use self::backup_stack::BackupStack;
|
||||
@@ -22,8 +18,8 @@ use futures::Poll;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::num::Wrapping;
|
||||
use std::sync::atomic::Ordering::{Acquire, AcqRel};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire};
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::thread;
|
||||
|
||||
@@ -100,15 +96,15 @@ impl Pool {
|
||||
//
|
||||
// This is `backup + pool_size` because the core thread pool running the
|
||||
// workers is spawned from backup as well.
|
||||
let backup = (0..total_size).map(|_| {
|
||||
Backup::new()
|
||||
}).collect::<Vec<_>>().into_boxed_slice();
|
||||
let backup = (0..total_size)
|
||||
.map(|_| Backup::new())
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice();
|
||||
|
||||
let backup_stack = BackupStack::new();
|
||||
|
||||
for i in (0..backup.len()).rev() {
|
||||
backup_stack.push(&backup, BackupId(i))
|
||||
.unwrap();
|
||||
backup_stack.push(&backup, BackupId(i)).unwrap();
|
||||
}
|
||||
|
||||
// Initialize the blocking state
|
||||
@@ -174,8 +170,10 @@ impl Pool {
|
||||
}
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if state == actual {
|
||||
state = next;
|
||||
@@ -299,8 +297,7 @@ impl Pool {
|
||||
}
|
||||
};
|
||||
|
||||
let need_spawn = self.backup[backup_id.0]
|
||||
.worker_handoff(id.clone());
|
||||
let need_spawn = self.backup[backup_id.0].worker_handoff(id.clone());
|
||||
|
||||
if !need_spawn {
|
||||
return;
|
||||
@@ -355,8 +352,7 @@ impl Pool {
|
||||
// available for future handoffs.
|
||||
//
|
||||
// This **must** happen before notifying the task.
|
||||
let res = pool.backup_stack
|
||||
.push(&pool.backup, backup_id);
|
||||
let res = pool.backup_stack.push(&pool.backup, backup_id);
|
||||
|
||||
if res.is_err() {
|
||||
// The pool is being shutdown.
|
||||
@@ -370,8 +366,7 @@ impl Pool {
|
||||
debug_assert!(pool.backup[backup_id.0].is_running());
|
||||
|
||||
// Wait for a handoff
|
||||
let handoff = pool.backup[backup_id.0]
|
||||
.wait_for_handoff(pool.config.keep_alive);
|
||||
let handoff = pool.backup[backup_id.0].wait_for_handoff(pool.config.keep_alive);
|
||||
|
||||
match handoff {
|
||||
Handoff::Worker(id) => {
|
||||
@@ -407,7 +402,8 @@ impl Pool {
|
||||
|
||||
debug_assert!(
|
||||
worker_state.lifecycle() != Signaled,
|
||||
"actual={:?}", worker_state.lifecycle(),
|
||||
"actual={:?}",
|
||||
worker_state.lifecycle(),
|
||||
);
|
||||
|
||||
trace!("signal_work -- notify; idx={}", idx);
|
||||
|
||||
@@ -82,8 +82,7 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn is_terminated(&self) -> bool {
|
||||
self.lifecycle() == Lifecycle::ShutdownNow &&
|
||||
self.num_futures() == 0
|
||||
self.lifecycle() == Lifecycle::ShutdownNow && self.num_futures() == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +114,10 @@ impl From<usize> for Lifecycle {
|
||||
use self::Lifecycle::*;
|
||||
|
||||
debug_assert!(
|
||||
src == Running as usize ||
|
||||
src == ShutdownOnIdle as usize ||
|
||||
src == ShutdownNow as usize);
|
||||
src == Running as usize
|
||||
|| src == ShutdownOnIdle as usize
|
||||
|| src == ShutdownNow as usize
|
||||
);
|
||||
|
||||
unsafe { ::std::mem::transmute(src) }
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use pool::{self, Pool, Lifecycle, MAX_FUTURES};
|
||||
use pool::{self, Lifecycle, Pool, MAX_FUTURES};
|
||||
use task::Task;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire};
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio_executor::{self, SpawnError};
|
||||
use futures::{future, Future};
|
||||
use tokio_executor::{self, SpawnError};
|
||||
|
||||
/// Submit futures to the associated thread pool for execution.
|
||||
///
|
||||
@@ -77,7 +77,8 @@ impl Sender {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn spawn<F>(&self, future: F) -> Result<(), SpawnError>
|
||||
where F: Future<Item = (), Error = ()> + Send + 'static,
|
||||
where
|
||||
F: Future<Item = (), Error = ()> + Send + 'static,
|
||||
{
|
||||
let mut s = self;
|
||||
tokio_executor::Executor::spawn(&mut s, Box::new(future))
|
||||
@@ -104,8 +105,11 @@ impl Sender {
|
||||
|
||||
next.inc_num_futures();
|
||||
|
||||
let actual = self.pool.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.pool
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
trace!("execute; count={:?}", next.num_futures());
|
||||
@@ -125,9 +129,10 @@ impl tokio_executor::Executor for Sender {
|
||||
tokio_executor::Executor::status(&s)
|
||||
}
|
||||
|
||||
fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
|
||||
-> Result<(), SpawnError>
|
||||
{
|
||||
fn spawn(
|
||||
&mut self,
|
||||
future: Box<Future<Item = (), Error = ()> + Send>,
|
||||
) -> Result<(), SpawnError> {
|
||||
let mut s = &*self;
|
||||
tokio_executor::Executor::spawn(&mut s, future)
|
||||
}
|
||||
@@ -150,9 +155,10 @@ impl<'a> tokio_executor::Executor for &'a Sender {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
|
||||
-> Result<(), SpawnError>
|
||||
{
|
||||
fn spawn(
|
||||
&mut self,
|
||||
future: Box<Future<Item = (), Error = ()> + Send>,
|
||||
) -> Result<(), SpawnError> {
|
||||
self.prepare_for_spawn()?;
|
||||
|
||||
// At this point, the pool has accepted the future, so schedule it for
|
||||
@@ -171,7 +177,8 @@ impl<'a> tokio_executor::Executor for &'a Sender {
|
||||
}
|
||||
|
||||
impl<T> future::Executor<T> for Sender
|
||||
where T: Future<Item = (), Error = ()> + Send + 'static,
|
||||
where
|
||||
T: Future<Item = (), Error = ()> + Send + 'static,
|
||||
{
|
||||
fn execute(&self, future: T) -> Result<(), future::ExecuteError<T>> {
|
||||
if let Err(e) = tokio_executor::Executor::status(self) {
|
||||
|
||||
@@ -2,8 +2,8 @@ use task::Task;
|
||||
use worker;
|
||||
|
||||
use crossbeam_deque::Injector;
|
||||
use futures::{Future, Poll, Async};
|
||||
use futures::task::AtomicTask;
|
||||
use futures::{Async, Future, Poll};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use pool::Pool;
|
||||
use task::{Task, BlockingState};
|
||||
use task::{BlockingState, Task};
|
||||
|
||||
use futures::{Poll, Async};
|
||||
use futures::{Async, Poll};
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::{Acquire, Release, AcqRel, Relaxed};
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
/// Manages the state around entering a blocking section and tasks that are
|
||||
@@ -172,10 +172,10 @@ impl Blocking {
|
||||
debug_assert_ne!(curr.0, 0);
|
||||
debug_assert_ne!(next.0, 0);
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
curr.into(),
|
||||
next.into(),
|
||||
AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(curr.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if curr == actual {
|
||||
break;
|
||||
@@ -190,8 +190,7 @@ impl Blocking {
|
||||
|
||||
// Finish pushing
|
||||
unsafe {
|
||||
(*prev).next_blocking
|
||||
.store(ptr as *mut _, Release);
|
||||
(*prev).next_blocking.store(ptr as *mut _, Release);
|
||||
}
|
||||
|
||||
// The node was queued to be notified once capacity is made
|
||||
@@ -245,7 +244,6 @@ impl Blocking {
|
||||
pub fn notify_task(&self, pool: &Arc<Pool>) {
|
||||
let prev = self.lock.fetch_add(1, AcqRel);
|
||||
|
||||
|
||||
if prev != 0 {
|
||||
// Another thread has the lock and will be responsible for notifying
|
||||
// pending tasks.
|
||||
@@ -287,8 +285,7 @@ impl Blocking {
|
||||
/// there are no more tasks to pop, `rem` is used to set the remaining
|
||||
/// capacity.
|
||||
fn pop(&self, rem: usize) -> Option<Arc<Task>> {
|
||||
'outer:
|
||||
loop {
|
||||
'outer: loop {
|
||||
unsafe {
|
||||
let mut tail = *self.tail.get();
|
||||
let mut next = (*tail).next_blocking.load(Acquire);
|
||||
@@ -330,10 +327,10 @@ impl Blocking {
|
||||
// pops that will come after the current one.
|
||||
after.add_capacity(rem + 1, &self.stub);
|
||||
|
||||
let actual: State = self.state.compare_and_swap(
|
||||
curr.into(),
|
||||
after.into(),
|
||||
AcqRel).into();
|
||||
let actual: State = self
|
||||
.state
|
||||
.compare_and_swap(curr.into(), after.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == curr {
|
||||
// Successfully returned the remaining capacity
|
||||
|
||||
@@ -9,14 +9,14 @@ use self::state::State;
|
||||
use notifier::Notifier;
|
||||
use pool::Pool;
|
||||
|
||||
use futures::{self, Future, Async};
|
||||
use futures::executor::{self, Spawn};
|
||||
use futures::{self, Async, Future};
|
||||
|
||||
use std::{fmt, panic, ptr};
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
|
||||
use std::sync::atomic::{AtomicPtr, AtomicUsize};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, AtomicPtr};
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire, Release, Relaxed};
|
||||
use std::{fmt, panic, ptr};
|
||||
|
||||
/// Harness around a future.
|
||||
///
|
||||
@@ -103,15 +103,20 @@ impl Task {
|
||||
|
||||
// Transition task to running state. At this point, the task must be
|
||||
// scheduled.
|
||||
let actual: State = self.state.compare_and_swap(
|
||||
Scheduled.into(), Running.into(), AcqRel).into();
|
||||
let actual: State = self
|
||||
.state
|
||||
.compare_and_swap(Scheduled.into(), Running.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
match actual {
|
||||
Scheduled => {},
|
||||
Scheduled => {}
|
||||
_ => panic!("unexpected task state; {:?}", actual),
|
||||
}
|
||||
|
||||
trace!("Task::run; state={:?}", State::from(self.state.load(Relaxed)));
|
||||
trace!(
|
||||
"Task::run; state={:?}",
|
||||
State::from(self.state.load(Relaxed))
|
||||
);
|
||||
|
||||
// The transition to `Running` done above ensures that a lock on the
|
||||
// future has been obtained.
|
||||
@@ -136,8 +141,10 @@ impl Task {
|
||||
|
||||
let mut g = Guard(fut, true);
|
||||
|
||||
let ret = g.0.as_mut().unwrap()
|
||||
.poll_future_notify(unpark, self as *const _ as usize);
|
||||
let ret =
|
||||
g.0.as_mut()
|
||||
.unwrap()
|
||||
.poll_future_notify(unpark, self as *const _ as usize);
|
||||
|
||||
g.1 = false;
|
||||
|
||||
@@ -168,8 +175,10 @@ impl Task {
|
||||
// fails, then the task has been unparked concurrent to running,
|
||||
// in which case it transitions immediately back to scheduled
|
||||
// and we return `true`.
|
||||
let prev: State = self.state.compare_and_swap(
|
||||
Running.into(), Idle.into(), AcqRel).into();
|
||||
let prev: State = self
|
||||
.state
|
||||
.compare_and_swap(Running.into(), Idle.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
match prev {
|
||||
Running => Run::Idle,
|
||||
@@ -202,10 +211,10 @@ impl Task {
|
||||
}
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(),
|
||||
Aborted.into(),
|
||||
AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), Aborted.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
// The future has been aborted. Drop it immediately to free resources and run drop
|
||||
@@ -239,10 +248,10 @@ impl Task {
|
||||
|
||||
loop {
|
||||
// Scheduling can only be done from the `Idle` state.
|
||||
let actual = self.state.compare_and_swap(
|
||||
Idle.into(),
|
||||
Scheduled.into(),
|
||||
AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(Idle.into(), Scheduled.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
match actual {
|
||||
Idle => return true,
|
||||
@@ -250,8 +259,10 @@ impl Task {
|
||||
// The task is already running on another thread. Transition
|
||||
// the state to `Notified`. If this CAS fails, then restart
|
||||
// the logic again from `Idle`.
|
||||
let actual = self.state.compare_and_swap(
|
||||
Running.into(), Notified.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(Running.into(), Notified.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
match actual {
|
||||
Idle => continue,
|
||||
|
||||
@@ -41,8 +41,10 @@ impl From<usize> for State {
|
||||
use self::State::*;
|
||||
|
||||
debug_assert!(
|
||||
src >= Idle as usize &&
|
||||
src <= Aborted as usize, "actual={}", src);
|
||||
src >= Idle as usize && src <= Aborted as usize,
|
||||
"actual={}",
|
||||
src
|
||||
);
|
||||
|
||||
unsafe { ::std::mem::transmute(src) }
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use pool::Pool;
|
||||
use sender::Sender;
|
||||
use shutdown::{Shutdown, ShutdownTrigger};
|
||||
|
||||
use futures::{Future, Poll};
|
||||
use futures::sync::oneshot;
|
||||
use futures::{Future, Poll};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -36,10 +36,7 @@ impl ThreadPool {
|
||||
Builder::new().build()
|
||||
}
|
||||
|
||||
pub(crate) fn new2(
|
||||
pool: Arc<Pool>,
|
||||
trigger: Arc<ShutdownTrigger>,
|
||||
) -> ThreadPool {
|
||||
pub(crate) fn new2(pool: Arc<Pool>, trigger: Arc<ShutdownTrigger>) -> ThreadPool {
|
||||
ThreadPool {
|
||||
inner: Some(Inner {
|
||||
sender: Sender { pool },
|
||||
@@ -80,18 +77,19 @@ impl ThreadPool {
|
||||
/// This function panics if the spawn fails. Use [`Sender::spawn`] for a
|
||||
/// version that returns a `Result` instead of panicking.
|
||||
pub fn spawn<F>(&self, future: F)
|
||||
where F: Future<Item = (), Error = ()> + Send + 'static,
|
||||
where
|
||||
F: Future<Item = (), Error = ()> + Send + 'static,
|
||||
{
|
||||
self.sender().spawn(future).unwrap();
|
||||
}
|
||||
|
||||
/// Spawn a future on to the thread pool, return a future representing
|
||||
/// Spawn a future on to the thread pool, return a future representing
|
||||
/// the produced value.
|
||||
///
|
||||
/// The SpawnHandle returned is a future that is a proxy for future itself.
|
||||
/// When future completes on this thread pool then the SpawnHandle will itself
|
||||
///
|
||||
/// The SpawnHandle returned is a future that is a proxy for future itself.
|
||||
/// When future completes on this thread pool then the SpawnHandle will itself
|
||||
/// be resolved.
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
@@ -105,7 +103,7 @@ impl ThreadPool {
|
||||
/// let thread_pool = ThreadPool::new();
|
||||
///
|
||||
/// let handle = thread_pool.spawn_handle(lazy(|| Ok::<_, ()>(42)));
|
||||
///
|
||||
///
|
||||
/// let value = handle.wait().unwrap();
|
||||
/// assert_eq!(value, 42);
|
||||
///
|
||||
@@ -116,9 +114,9 @@ impl ThreadPool {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the spawn fails.
|
||||
/// This function panics if the spawn fails.
|
||||
pub fn spawn_handle<F>(&self, future: F) -> SpawnHandle<F::Item, F::Error>
|
||||
where
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
F::Item: Send + 'static,
|
||||
F::Error: Send + 'static,
|
||||
@@ -201,10 +199,10 @@ impl Drop for ThreadPool {
|
||||
}
|
||||
|
||||
/// Handle returned from ThreadPool::spawn_handle.
|
||||
///
|
||||
/// This handle is a future representing the completion of a different future
|
||||
/// spawned on to the thread pool. Created through the ThreadPool::spawn_handle
|
||||
/// function this handle will resolve when the future provided resolves on the
|
||||
///
|
||||
/// This handle is a future representing the completion of a different future
|
||||
/// spawned on to the thread pool. Created through the ThreadPool::spawn_handle
|
||||
/// function this handle will resolve when the future provided resolves on the
|
||||
/// thread pool.
|
||||
#[derive(Debug)]
|
||||
pub struct SpawnHandle<T, E>(oneshot::SpawnHandle<T, E>);
|
||||
|
||||
@@ -4,9 +4,9 @@ use worker::state::{State, PUSHED_MASK};
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::atomic::Ordering::{Acquire, AcqRel, Relaxed, Release};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use crossbeam_deque::{Steal, Stealer, Worker};
|
||||
@@ -102,9 +102,10 @@ impl WorkerEntry {
|
||||
let mut next = state;
|
||||
next.notify();
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(),
|
||||
AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if state == actual {
|
||||
break;
|
||||
@@ -169,8 +170,10 @@ impl WorkerEntry {
|
||||
|
||||
next.set_lifecycle(Signaled);
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
break;
|
||||
@@ -307,7 +310,9 @@ impl WorkerEntry {
|
||||
|
||||
#[inline]
|
||||
pub fn set_next_sleeper(&self, val: usize) {
|
||||
unsafe { *self.next_sleeper.get() = val; }
|
||||
unsafe {
|
||||
*self.next_sleeper.get() = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,24 +2,19 @@ mod entry;
|
||||
mod stack;
|
||||
mod state;
|
||||
|
||||
pub(crate) use self::entry::{
|
||||
WorkerEntry as Entry,
|
||||
};
|
||||
pub(crate) use self::entry::WorkerEntry as Entry;
|
||||
pub(crate) use self::stack::Stack;
|
||||
pub(crate) use self::state::{
|
||||
State,
|
||||
Lifecycle,
|
||||
};
|
||||
pub(crate) use self::state::{Lifecycle, State};
|
||||
|
||||
use pool::{self, Pool, BackupId};
|
||||
use notifier::Notifier;
|
||||
use pool::{self, BackupId, Pool};
|
||||
use sender::Sender;
|
||||
use shutdown::ShutdownTrigger;
|
||||
use task::{self, Task, CanBlock};
|
||||
use task::{self, CanBlock, Task};
|
||||
|
||||
use tokio_executor;
|
||||
|
||||
use futures::{Poll, Async};
|
||||
use futures::{Async, Poll};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
@@ -339,8 +334,11 @@ impl Worker {
|
||||
}
|
||||
}
|
||||
|
||||
let actual = self.entry().state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.entry()
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
break;
|
||||
@@ -417,8 +415,11 @@ impl Worker {
|
||||
|
||||
self.run_task(task, notify);
|
||||
|
||||
trace!("try_steal_task -- signal_work; self={}; from={}",
|
||||
self.id.0, idx);
|
||||
trace!(
|
||||
"try_steal_task -- signal_work; self={}; from={}",
|
||||
self.id.0,
|
||||
idx
|
||||
);
|
||||
|
||||
// Signal other workers that work is available
|
||||
//
|
||||
@@ -485,8 +486,11 @@ impl Worker {
|
||||
let mut next = state;
|
||||
next.dec_num_futures();
|
||||
|
||||
let actual = self.pool.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.pool
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
trace!("task complete; state={:?}", next);
|
||||
@@ -526,11 +530,7 @@ impl Worker {
|
||||
///
|
||||
/// Great care is needed to ensure that `current_task` is unset in this
|
||||
/// function.
|
||||
fn run_task2(&self,
|
||||
task: &Arc<Task>,
|
||||
notify: &Arc<Notifier>)
|
||||
-> task::Run
|
||||
{
|
||||
fn run_task2(&self, task: &Arc<Task>, notify: &Arc<Notifier>) -> task::Run {
|
||||
struct Guard<'a> {
|
||||
worker: &'a Worker,
|
||||
}
|
||||
@@ -562,9 +562,7 @@ impl Worker {
|
||||
|
||||
// Create the guard, this ensures that `current_task` is unset when the
|
||||
// function returns, even if the return is caused by a panic.
|
||||
let _g = Guard {
|
||||
worker: self,
|
||||
};
|
||||
let _g = Guard { worker: self };
|
||||
|
||||
task.run(notify)
|
||||
}
|
||||
@@ -609,8 +607,11 @@ impl Worker {
|
||||
}
|
||||
}
|
||||
|
||||
let actual = self.entry().state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.entry()
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
if state.is_notified() {
|
||||
@@ -668,8 +669,11 @@ impl Worker {
|
||||
let mut next = state;
|
||||
next.set_lifecycle(Running);
|
||||
|
||||
let actual = self.entry().state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.entry()
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
return true;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use config::MAX_WORKERS;
|
||||
use worker;
|
||||
|
||||
use std::{fmt, usize};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::{Acquire, AcqRel, Relaxed};
|
||||
use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed};
|
||||
use std::{fmt, usize};
|
||||
|
||||
/// Lock-free stack of sleeping workers.
|
||||
///
|
||||
@@ -90,8 +90,10 @@ impl Stack {
|
||||
entries[idx].set_next_sleeper(head);
|
||||
next.set_head(idx);
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if state == actual {
|
||||
return Ok(());
|
||||
@@ -112,11 +114,12 @@ impl Stack {
|
||||
/// Returns the index of the popped worker and the worker's observed state.
|
||||
///
|
||||
/// `None` if the stack is empty.
|
||||
pub fn pop(&self, entries: &[worker::Entry],
|
||||
max_lifecycle: worker::Lifecycle,
|
||||
terminate: bool)
|
||||
-> Option<(usize, worker::State)>
|
||||
{
|
||||
pub fn pop(
|
||||
&self,
|
||||
entries: &[worker::Entry],
|
||||
max_lifecycle: worker::Lifecycle,
|
||||
terminate: bool,
|
||||
) -> Option<(usize, worker::State)> {
|
||||
// Figure out the empty value
|
||||
let terminal = match terminate {
|
||||
true => TERMINATED,
|
||||
@@ -145,8 +148,10 @@ impl Stack {
|
||||
return None;
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual != state {
|
||||
state = actual;
|
||||
@@ -173,8 +178,10 @@ impl Stack {
|
||||
next.set_head(next_head);
|
||||
}
|
||||
|
||||
let actual = self.state.compare_and_swap(
|
||||
state.into(), next.into(), AcqRel).into();
|
||||
let actual = self
|
||||
.state
|
||||
.compare_and_swap(state.into(), next.into(), AcqRel)
|
||||
.into();
|
||||
|
||||
if actual == state {
|
||||
// Release ordering is needed to ensure that unsetting the
|
||||
|
||||
@@ -108,11 +108,12 @@ impl From<usize> for Lifecycle {
|
||||
use self::Lifecycle::*;
|
||||
|
||||
debug_assert!(
|
||||
src == Shutdown as usize ||
|
||||
src == Running as usize ||
|
||||
src == Sleeping as usize ||
|
||||
src == Notified as usize ||
|
||||
src == Signaled as usize);
|
||||
src == Shutdown as usize
|
||||
|| src == Running as usize
|
||||
|| src == Sleeping as usize
|
||||
|| src == Notified as usize
|
||||
|| src == Signaled as usize
|
||||
);
|
||||
|
||||
unsafe { ::std::mem::transmute(src) }
|
||||
}
|
||||
@@ -128,18 +129,12 @@ impl From<Lifecycle> for usize {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use super::Lifecycle::*;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lifecycle_encode() {
|
||||
let lifecycles = &[
|
||||
Shutdown,
|
||||
Running,
|
||||
Sleeping,
|
||||
Notified,
|
||||
Signaled,
|
||||
];
|
||||
let lifecycles = &[Shutdown, Running, Sleeping, Notified, Signaled];
|
||||
|
||||
for &lifecycle in lifecycles {
|
||||
let mut v: usize = lifecycle.into();
|
||||
|
||||
@@ -6,24 +6,21 @@ extern crate rand;
|
||||
|
||||
use tokio_threadpool::*;
|
||||
|
||||
use futures::*;
|
||||
use futures::future::{lazy, poll_fn};
|
||||
use futures::*;
|
||||
use rand::*;
|
||||
|
||||
use std::sync::*;
|
||||
use std::sync::atomic::*;
|
||||
use std::sync::atomic::Ordering::*;
|
||||
use std::time::Duration;
|
||||
use std::sync::atomic::*;
|
||||
use std::sync::*;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let _ = ::env_logger::try_init();
|
||||
|
||||
let pool = Builder::new()
|
||||
.pool_size(1)
|
||||
.max_blocking(1)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(1).max_blocking(1).build();
|
||||
|
||||
let (tx1, rx1) = mpsc::channel();
|
||||
let (tx2, rx2) = mpsc::channel();
|
||||
@@ -32,7 +29,8 @@ fn basic() {
|
||||
let res = blocking(|| {
|
||||
let v = rx1.recv().unwrap();
|
||||
tx2.send(v).unwrap();
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert!(res.is_ready());
|
||||
Ok(().into())
|
||||
@@ -50,10 +48,7 @@ fn basic() {
|
||||
fn notify_task_on_capacity() {
|
||||
const BLOCKING: usize = 10;
|
||||
|
||||
let pool = Builder::new()
|
||||
.pool_size(1)
|
||||
.max_blocking(1)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(1).max_blocking(1).build();
|
||||
|
||||
let rem = Arc::new(AtomicUsize::new(BLOCKING));
|
||||
let (tx, rx) = mpsc::channel();
|
||||
@@ -71,7 +66,8 @@ fn notify_task_on_capacity() {
|
||||
if prev == 1 {
|
||||
tx.send(()).unwrap();
|
||||
}
|
||||
}).map_err(|e| panic!("blocking err {:?}", e))
|
||||
})
|
||||
.map_err(|e| panic!("blocking err {:?}", e))
|
||||
})
|
||||
}));
|
||||
}
|
||||
@@ -83,17 +79,14 @@ fn notify_task_on_capacity() {
|
||||
|
||||
#[test]
|
||||
fn capacity_is_use_it_or_lose_it() {
|
||||
use futures::*;
|
||||
use futures::Async::*;
|
||||
use futures::sync::oneshot;
|
||||
use futures::task::Task;
|
||||
use futures::Async::*;
|
||||
use futures::*;
|
||||
|
||||
// TODO: Run w/ bigger pool size
|
||||
|
||||
let pool = Builder::new()
|
||||
.pool_size(1)
|
||||
.max_blocking(1)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(1).max_blocking(1).build();
|
||||
|
||||
let (tx1, rx1) = mpsc::channel();
|
||||
let (tx2, rx2) = oneshot::channel();
|
||||
@@ -105,24 +98,24 @@ fn capacity_is_use_it_or_lose_it() {
|
||||
poll_fn(move || {
|
||||
blocking(|| {
|
||||
rx1.recv().unwrap();
|
||||
}).map_err(|_| panic!())
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
}));
|
||||
|
||||
pool.spawn(lazy(move || {
|
||||
rx2
|
||||
.map_err(|_| panic!())
|
||||
.and_then(|task: Task| {
|
||||
poll_fn(move || {
|
||||
blocking(|| {
|
||||
// Notify the other task
|
||||
task.notify();
|
||||
rx2.map_err(|_| panic!()).and_then(|task: Task| {
|
||||
poll_fn(move || {
|
||||
blocking(|| {
|
||||
// Notify the other task
|
||||
task.notify();
|
||||
|
||||
// Block until woken
|
||||
rx3.recv().unwrap();
|
||||
}).map_err(|_| panic!())
|
||||
// Block until woken
|
||||
rx3.recv().unwrap();
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
})
|
||||
}));
|
||||
|
||||
// Spawn a future that will try to block, get notified, then not actually
|
||||
@@ -136,8 +129,7 @@ fn capacity_is_use_it_or_lose_it() {
|
||||
0 => {
|
||||
i = 1;
|
||||
|
||||
let res = blocking(|| unreachable!())
|
||||
.map_err(|_| panic!());
|
||||
let res = blocking(|| unreachable!()).map_err(|_| panic!());
|
||||
|
||||
assert!(res.unwrap().is_not_ready());
|
||||
|
||||
@@ -157,8 +149,7 @@ fn capacity_is_use_it_or_lose_it() {
|
||||
return Ok(NotReady);
|
||||
}
|
||||
2 => {
|
||||
let res = blocking(|| unreachable!())
|
||||
.map_err(|_| panic!());
|
||||
let res = blocking(|| unreachable!()).map_err(|_| panic!());
|
||||
|
||||
assert!(res.unwrap().is_not_ready());
|
||||
|
||||
@@ -177,10 +168,7 @@ fn capacity_is_use_it_or_lose_it() {
|
||||
|
||||
#[test]
|
||||
fn blocking_thread_does_not_take_over_shutdown_worker_thread() {
|
||||
let pool = Builder::new()
|
||||
.pool_size(2)
|
||||
.max_blocking(1)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(2).max_blocking(1).build();
|
||||
|
||||
let (enter_tx, enter_rx) = mpsc::channel();
|
||||
let (exit_tx, exit_rx) = mpsc::channel();
|
||||
@@ -197,7 +185,8 @@ fn blocking_thread_does_not_take_over_shutdown_worker_thread() {
|
||||
enter_tx.send(()).unwrap();
|
||||
exit_rx.recv().unwrap();
|
||||
exited.store(true, Relaxed);
|
||||
}).map_err(|_| panic!())
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
}));
|
||||
}
|
||||
@@ -208,13 +197,9 @@ fn blocking_thread_does_not_take_over_shutdown_worker_thread() {
|
||||
// Spawn another task that attempts to block
|
||||
pool.spawn(lazy(move || {
|
||||
poll_fn(move || {
|
||||
let res = blocking(|| {
|
||||
let res = blocking(|| {}).unwrap();
|
||||
|
||||
}).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
res.is_ready(),
|
||||
exited.load(Relaxed));
|
||||
assert_eq!(res.is_ready(), exited.load(Relaxed));
|
||||
|
||||
try_tx.send(res.is_ready()).unwrap();
|
||||
|
||||
@@ -242,10 +227,7 @@ fn blocking_one_time_gets_capacity_for_multiple_blocks() {
|
||||
const BLOCKING: usize = 2;
|
||||
|
||||
for _ in 0..ITER {
|
||||
let pool = Builder::new()
|
||||
.pool_size(4)
|
||||
.max_blocking(1)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(4).max_blocking(1).build();
|
||||
|
||||
let rem = Arc::new(AtomicUsize::new(BLOCKING));
|
||||
let (tx, rx) = mpsc::channel();
|
||||
@@ -259,7 +241,8 @@ fn blocking_one_time_gets_capacity_for_multiple_blocks() {
|
||||
// First block
|
||||
let res = blocking(|| {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
}).map_err(|e| panic!("blocking err {:?}", e));
|
||||
})
|
||||
.map_err(|e| panic!("blocking err {:?}", e));
|
||||
|
||||
try_ready!(res);
|
||||
|
||||
@@ -302,8 +285,12 @@ fn shutdown() {
|
||||
Builder::new()
|
||||
.pool_size(1)
|
||||
.max_blocking(BLOCKING)
|
||||
.after_start(move || { num_inc.fetch_add(1, Relaxed); })
|
||||
.before_stop(move || { num_dec.fetch_add(1, Relaxed); })
|
||||
.after_start(move || {
|
||||
num_inc.fetch_add(1, Relaxed);
|
||||
})
|
||||
.before_stop(move || {
|
||||
num_dec.fetch_add(1, Relaxed);
|
||||
})
|
||||
.build()
|
||||
};
|
||||
|
||||
@@ -317,7 +304,8 @@ fn shutdown() {
|
||||
let res = blocking(|| {
|
||||
barrier.wait();
|
||||
Ok::<_, ()>(())
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
tx.send(()).unwrap();
|
||||
|
||||
@@ -394,7 +382,8 @@ fn hammer() {
|
||||
}
|
||||
|
||||
cnt_block.fetch_add(1, Relaxed);
|
||||
}).map_err(|_| panic!())
|
||||
})
|
||||
.map_err(|_| panic!())
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@ extern crate tokio_threadpool;
|
||||
|
||||
use tokio_threadpool::*;
|
||||
|
||||
use futures::{Future, Stream, Sink, Poll};
|
||||
use futures::{Future, Poll, Sink, Stream};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
fn hammer() {
|
||||
use futures::future;
|
||||
use futures::sync::{oneshot, mpsc};
|
||||
use futures::sync::{mpsc, oneshot};
|
||||
|
||||
const N: usize = 1000;
|
||||
const ITER: usize = 20;
|
||||
@@ -37,7 +37,7 @@ fn hammer() {
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0.. ITER {
|
||||
for _ in 0..ITER {
|
||||
let pool = Builder::new()
|
||||
// .pool_size(30)
|
||||
.build();
|
||||
@@ -61,14 +61,13 @@ fn hammer() {
|
||||
rx2
|
||||
})
|
||||
.map_err(|e| panic!("e={:?}", e))
|
||||
.and_then(|_| {
|
||||
Ok(())
|
||||
});
|
||||
.and_then(|_| Ok(()));
|
||||
|
||||
pool.spawn(Counted {
|
||||
inner: task,
|
||||
cnt: c1.clone(),
|
||||
}).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
});
|
||||
@@ -85,17 +84,12 @@ fn hammer() {
|
||||
listen_tx.send(tx).unwrap();
|
||||
|
||||
pool.spawn({
|
||||
let task = rx
|
||||
.map_err(|e| panic!("rx err={:?}", e))
|
||||
.and_then(|tx| {
|
||||
tx.send(()).unwrap();
|
||||
Ok(())
|
||||
});
|
||||
let task = rx.map_err(|e| panic!("rx err={:?}", e)).and_then(|tx| {
|
||||
tx.send(()).unwrap();
|
||||
Ok(())
|
||||
});
|
||||
|
||||
Counted {
|
||||
inner: task,
|
||||
cnt,
|
||||
}
|
||||
Counted { inner: task, cnt }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
extern crate tokio_threadpool;
|
||||
extern crate tokio_executor;
|
||||
extern crate futures;
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
extern crate tokio_executor;
|
||||
extern crate tokio_threadpool;
|
||||
|
||||
use tokio_executor::park::{Park, Unpark};
|
||||
use tokio_threadpool::*;
|
||||
use tokio_threadpool::park::{DefaultPark, DefaultUnpark};
|
||||
use tokio_threadpool::*;
|
||||
|
||||
use futures::{Poll, Sink, Stream, Async, Future};
|
||||
use futures::future::lazy;
|
||||
use futures::{Async, Future, Poll, Sink, Stream};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::sync::atomic::*;
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use std::sync::atomic::*;
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::time::Duration;
|
||||
|
||||
thread_local!(static FOO: Cell<u32> = Cell::new(0));
|
||||
@@ -56,7 +56,8 @@ fn natural_shutdown_simple_futures() {
|
||||
|
||||
t.send("one").unwrap();
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
rx
|
||||
};
|
||||
|
||||
@@ -68,7 +69,8 @@ fn natural_shutdown_simple_futures() {
|
||||
|
||||
t.send("two").unwrap();
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
rx
|
||||
};
|
||||
|
||||
@@ -223,7 +225,8 @@ fn many_oneshot_futures() {
|
||||
tx.spawn(lazy(move || {
|
||||
cnt.fetch_add(1, Relaxed);
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Wait for the pool to shutdown
|
||||
@@ -257,15 +260,17 @@ fn many_multishot_futures() {
|
||||
for _ in 0..CHAIN {
|
||||
let (next_tx, next_rx) = mpsc::channel(10);
|
||||
|
||||
let rx = chain_rx
|
||||
.map_err(|e| panic!("{:?}", e));
|
||||
let rx = chain_rx.map_err(|e| panic!("{:?}", e));
|
||||
|
||||
// Forward all the messages
|
||||
pool_tx.spawn(next_tx
|
||||
.send_all(rx)
|
||||
.map(|_| ())
|
||||
.map_err(|e| panic!("{:?}", e))
|
||||
).unwrap();
|
||||
pool_tx
|
||||
.spawn(
|
||||
next_tx
|
||||
.send_all(rx)
|
||||
.map(|_| ())
|
||||
.map_err(|e| panic!("{:?}", e)),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
chain_rx = next_rx;
|
||||
}
|
||||
@@ -321,7 +326,8 @@ fn global_executor_is_configured() {
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
signal_rx.recv().unwrap();
|
||||
|
||||
@@ -339,17 +345,12 @@ fn busy_threadpool_is_not_idle() {
|
||||
use futures::sync::oneshot;
|
||||
|
||||
// let pool = ThreadPool::new();
|
||||
let pool = Builder::new()
|
||||
.pool_size(4)
|
||||
.max_blocking(2)
|
||||
.build();
|
||||
let pool = Builder::new().pool_size(4).max_blocking(2).build();
|
||||
let tx = pool.sender().clone();
|
||||
|
||||
let (term_tx, term_rx) = oneshot::channel();
|
||||
|
||||
tx.spawn(term_rx.then(|_| {
|
||||
Ok(())
|
||||
})).unwrap();
|
||||
tx.spawn(term_rx.then(|_| Ok(()))).unwrap();
|
||||
|
||||
let mut idle = pool.shutdown_on_idle();
|
||||
|
||||
@@ -426,7 +427,7 @@ fn multi_threadpool() {
|
||||
|
||||
#[test]
|
||||
fn eagerly_drops_futures() {
|
||||
use futures::future::{Future, lazy, empty};
|
||||
use futures::future::{empty, lazy, Future};
|
||||
use futures::task;
|
||||
use std::sync::mpsc;
|
||||
|
||||
@@ -486,12 +487,10 @@ fn eagerly_drops_futures() {
|
||||
let notify_on_drop = NotifyOnDrop(drop_tx);
|
||||
|
||||
let pool = tokio_threadpool::Builder::new()
|
||||
.custom_park(move |_| {
|
||||
MyPark {
|
||||
inner: DefaultPark::new(),
|
||||
park_tx: park_tx.clone(),
|
||||
unpark_tx: unpark_tx.clone(),
|
||||
}
|
||||
.custom_park(move |_| MyPark {
|
||||
inner: DefaultPark::new(),
|
||||
park_tx: park_tx.clone(),
|
||||
unpark_tx: unpark_tx.clone(),
|
||||
})
|
||||
.build();
|
||||
|
||||
@@ -506,7 +505,9 @@ fn eagerly_drops_futures() {
|
||||
// `notify_on_drop` handle.
|
||||
empty::<(), ()>().then(move |_| {
|
||||
// This code path should never be reached.
|
||||
if true { panic!() }
|
||||
if true {
|
||||
panic!()
|
||||
}
|
||||
|
||||
// Explicitly drop `notify_on_drop` here, this is mostly to ensure
|
||||
// that the `notify_on_drop` handle gets moved into the task. It
|
||||
|
||||
Reference in New Issue
Block a user