use core::fmt;
pub unsafe trait UnsafeWake {
unsafe fn clone_raw(&self) -> Waker;
unsafe fn drop_raw(&self);
unsafe fn wake(&self);
}
pub struct Waker {
inner: *const UnsafeWake,
}
unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}
impl Waker {
#[inline]
pub unsafe fn new(inner: *const 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;
use core::marker::PhantomData;
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>, *const ArcWrapped<T>>(rc);
Waker::new(ptr)
}
}
}
}