use worker::Worker;
use futures::{Async, Poll};
use tokio_executor;
use std::error::Error;
use std::fmt;
mod global;
pub use self::global::blocking;
#[doc(hidden)]
pub use self::global::{set_default, with_default, DefaultGuard};
pub struct BlockingError {
_p: (),
}
#[doc(hidden)]
pub type BlockingImpl = fn(&mut dyn FnMut()) -> Poll<(), BlockingError>;
fn default_blocking(f: &mut dyn FnMut()) -> Poll<(), BlockingError> {
let res = Worker::with_current(|worker| {
let worker = match worker {
Some(worker) => worker,
None => {
return Err(BlockingError::new());
}
};
worker.transition_to_blocking()
});
try_ready!(res);
tokio_executor::exit(move || (f)());
Worker::with_current(|worker| {
worker.unwrap().transition_from_blocking();
});
Ok(Async::Ready(()))
}
impl BlockingError {
#[doc(hidden)]
pub fn new() -> Self {
Self { _p: () }
}
}
impl fmt::Display for BlockingError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.description())
}
}
impl fmt::Debug for BlockingError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("BlockingError")
.field("reason", &self.description())
.finish()
}
}
impl Error for BlockingError {
fn description(&self) -> &str {
"`blocking` annotation used from outside the context of a thread pool"
}
}