use core::fmt;
if_std! {
use core::marker::PhantomData;
use never::Never;
use executor::Executor;
type Exec<'a> = &'a mut Executor;
}
if_not_std! {
type Exec<'a> = ();
}
mod atomic_waker;
pub use self::atomic_waker::AtomicWaker;
pub struct Context<'a> {
waker: &'a Waker,
map: &'a mut LocalMap,
executor: Exec<'a>,
}
impl<'a> Context<'a> {
pub fn waker(&self) -> Waker {
self.waker.clone()
}
pub fn with_waker<'b>(&'b mut self, waker: &'b Waker) -> Context<'b> {
Context { map: self.map, executor: self.executor, waker }
}
pub fn with_locals<'b>(&'b mut self, map: &'b mut LocalMap)
-> Context<'b>
{
Context { map, waker: self.waker, executor: self.executor }
}
}
if_std! {
use std::boxed::Box;
use Future;
impl<'a> Context<'a> {
pub fn new(map: &'a mut LocalMap, waker: &'a Waker, executor: &'a mut Executor) -> Context<'a> {
Context { waker, map, executor }
}
pub fn executor(&mut self) -> &mut Executor {
self.executor
}
pub fn spawn<F>(&mut self, f: F)
where F: Future<Item = (), Error = Never> + 'static + Send
{
self.executor.spawn(Box::new(f)).unwrap()
}
}
}
if_not_std! {
impl<'a> Context<'a> {
pub fn new(map: &'a mut LocalMap, waker: &'a Waker) -> Context<'a> {
Context { waker, map, executor: () }
}
}
}
impl<'a> fmt::Debug for Context<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Context")
.finish()
}
}
pub struct LocalMap {
#[allow(dead_code)]
inner: data::LocalMap,
}
impl LocalMap {
pub fn new() -> LocalMap {
LocalMap { inner: data::local_map() }
}
}
impl fmt::Debug for LocalMap {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("LocalMap")
.finish()
}
}
pub unsafe trait UnsafeWake {
unsafe fn clone_raw(&self) -> Waker;
unsafe fn drop_raw(&self);
unsafe fn wake(&self);
}
pub struct Waker {
inner: *mut UnsafeWake,
}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}
impl Waker {
#[inline]
pub unsafe fn new(inner: *mut UnsafeWake) -> Waker {
Waker { inner: inner }
}
pub fn wake(&self) {
unsafe { (*self.inner).wake() }
}
pub fn will_wake(&self, other: &Waker) -> bool {
self.inner == other.inner
}
}
impl Clone for Waker {
#[inline]
fn clone(&self) -> Self {
unsafe {
(*self.inner).clone_raw()
}
}
}
impl fmt::Debug for Waker {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Waker")
.finish()
}
}
impl Drop for Waker {
fn drop(&mut self) {
unsafe {
(*self.inner).drop_raw()
}
}
}
if_std! {
use std::mem;
use std::ptr;
use std::sync::Arc;
mod data;
pub use self::data::LocalKey;
pub trait Wake: Send + Sync {
fn wake(arc_self: &Arc<Self>);
}
struct ArcWrapped<T>(PhantomData<T>);
unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
unsafe fn clone_raw(&self) -> Waker {
let me: *const ArcWrapped<T> = self;
let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
Waker::from(arc)
}
unsafe fn drop_raw(&self) {
let mut me: *const ArcWrapped<T> = self;
let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
ptr::drop_in_place(me);
}
unsafe fn wake(&self) {
let me: *const ArcWrapped<T> = self;
T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
}
}
impl<T> From<Arc<T>> for Waker
where T: Wake + 'static,
{
fn from(rc: Arc<T>) -> Waker {
unsafe {
let ptr = mem::transmute::<Arc<T>, *mut ArcWrapped<T>>(rc);
Waker::new(ptr)
}
}
}
}
#[cfg(not(feature = "std"))]
mod data {
pub struct LocalMap;
pub fn local_map() -> LocalMap {
LocalMap
}
}