#![cfg_attr(feature = "use_std", allow(dead_code))]
use core::marker;
use core::mem;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
use core::sync::atomic::Ordering::{SeqCst, Relaxed};
use super::{BorrowedTask, NotifyHandle};
pub struct LocalKey;
pub struct LocalMap;
pub fn local_map() -> LocalMap { LocalMap }
#[derive(Copy, Clone)]
pub struct BorrowedEvents<'a>(marker::PhantomData<&'a ()>);
#[derive(Copy, Clone)]
pub struct BorrowedUnpark<'a> {
f: &'a Fn() -> NotifyHandle,
id: usize,
}
pub struct TaskUnpark {
handle: NotifyHandle,
id: usize,
}
#[derive(Clone)]
pub struct UnparkEvents;
impl<'a> BorrowedEvents<'a> {
pub fn new() -> BorrowedEvents<'a> {
BorrowedEvents(marker::PhantomData)
}
pub fn to_owned(&self) -> UnparkEvents {
UnparkEvents
}
}
impl<'a> BorrowedUnpark<'a> {
#[inline]
pub fn new(f: &'a Fn() -> NotifyHandle, id: usize) -> BorrowedUnpark<'a> {
BorrowedUnpark { f: f, id: id }
}
#[inline]
pub fn to_owned(&self) -> TaskUnpark {
let handle = (self.f)();
let id = handle.clone_id(self.id);
TaskUnpark { handle: handle, id: id }
}
}
impl UnparkEvents {
pub fn notify(&self) {}
pub fn will_notify(&self, _other: &BorrowedEvents) -> bool {
true
}
}
impl TaskUnpark {
pub fn notify(&self) {
self.handle.notify(self.id);
}
pub fn will_notify(&self, other: &BorrowedUnpark) -> bool {
self.id == other.id && self.handle.inner == (other.f)().inner
}
}
impl Clone for TaskUnpark {
fn clone(&self) -> TaskUnpark {
let handle = self.handle.clone();
let id = handle.clone_id(self.id);
TaskUnpark { handle: handle, id: id }
}
}
impl Drop for TaskUnpark {
fn drop(&mut self) {
self.handle.drop_id(self.id);
}
}
static GET: AtomicUsize = ATOMIC_USIZE_INIT;
static SET: AtomicUsize = ATOMIC_USIZE_INIT;
pub unsafe fn init(get: fn() -> *mut u8, set: fn(*mut u8)) -> bool {
if GET.compare_exchange(0, get as usize, SeqCst, SeqCst).is_ok() {
SET.store(set as usize, SeqCst);
true
} else {
false
}
}
#[inline]
pub fn get_ptr() -> Option<*mut u8> {
match GET.load(Relaxed) {
0 => None,
n => Some(unsafe { mem::transmute::<usize, fn() -> *mut u8>(n)() }),
}
}
#[cfg(feature = "use_std")]
#[inline]
pub fn is_get_ptr(f: usize) -> bool {
GET.load(Relaxed) == f
}
pub fn set<'a, F, R>(task: &BorrowedTask<'a>, f: F) -> R
where F: FnOnce() -> R
{
let set = match SET.load(Relaxed) {
0 => panic!("not initialized"),
n => unsafe { mem::transmute::<usize, fn(*mut u8)>(n) },
};
struct Reset(fn(*mut u8), *mut u8);
impl Drop for Reset {
#[inline]
fn drop(&mut self) {
(self.0)(self.1);
}
}
let _reset = Reset(set, get_ptr().unwrap());
set(task as *const _ as *mut u8);
f()
}