use super::{Executor, Enter, SpawnError};
use futures::Future;
use std::cell::Cell;
use std::marker::PhantomData;
use std::rc::Rc;
#[cfg(feature = "unstable-futures")]
use futures2;
#[derive(Debug, Clone)]
pub struct DefaultExecutor {
_p: PhantomData<Rc<()>>,
}
impl DefaultExecutor {
pub fn current() -> DefaultExecutor {
DefaultExecutor {
_p: PhantomData,
}
}
}
thread_local!(static EXECUTOR: Cell<Option<*mut Executor>> = Cell::new(None));
impl super::Executor for DefaultExecutor {
fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
-> Result<(), SpawnError>
{
EXECUTOR.with(|current_executor| {
match current_executor.get() {
Some(executor) => {
let executor = unsafe { &mut *executor };
executor.spawn(future)
}
None => {
Err(SpawnError::shutdown())
}
}
})
}
#[cfg(feature = "unstable-futures")]
fn spawn2(&mut self, future: Box<futures2::Future<Item = (), Error = futures2::Never> + Send>)
-> Result<(), futures2::executor::SpawnError>
{
EXECUTOR.with(|current_executor| {
match current_executor.get() {
Some(executor) => {
let executor = unsafe { &mut *executor };
executor.spawn2(future)
}
None => {
Err(futures2::executor::SpawnError::shutdown())
}
}
})
}
}
pub fn spawn<T>(future: T)
where T: Future<Item = (), Error = ()> + Send + 'static,
{
DefaultExecutor::current().spawn(Box::new(future))
.unwrap()
}
#[cfg(feature = "unstable-futures")]
pub fn spawn2<T>(future: T)
where T: futures2::Future<Item = (), Error = futures2::Never> + Send + 'static,
{
DefaultExecutor::current().spawn2(Box::new(future))
.unwrap()
}
pub fn with_default<T, F, R>(executor: &mut T, enter: &mut Enter, f: F) -> R
where T: Executor,
F: FnOnce(&mut Enter) -> R
{
EXECUTOR.with(|cell| {
assert!(cell.get().is_none(), "default executor already set for execution context");
struct Reset<'a>(&'a Cell<Option<*mut Executor>>);
impl<'a> Drop for Reset<'a> {
fn drop(&mut self) {
self.0.set(None);
}
}
let _reset = Reset(cell);
let executor = unsafe { hide_lt(executor as &mut _ as *mut _) };
cell.set(Some(executor));
f(enter)
})
}
unsafe fn hide_lt<'a>(p: *mut (Executor + 'a)) -> *mut (Executor + 'static) {
use std::mem;
mem::transmute(p)
}