mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-28 00:00:11 +02:00
chore: apply rustfmt to all crates (#917)
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user