use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::result::Result;
use private::{promise_node, Event, BoolEvent, PromiseAndFulfillerHub, PromiseAndFulfillerWrapper,
EVENT_LOOP, with_current_event_loop, PromiseNode};
#[macro_export]
macro_rules! pry {
($expr:expr) => (match $expr {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => {
return $crate::Promise::err(::std::convert::From::from(err))
}
})
}
mod private;
mod handle_table;
#[must_use]
pub struct Promise<T, E> where T: 'static, E: 'static {
node: Box<PromiseNode<T, E>>,
}
impl <T, E> Promise <T, E> {
pub fn ok(value: T) -> Promise<T, E> {
Promise { node: Box::new(promise_node::Immediate::new(Ok(value))) }
}
pub fn err(error: E) -> Promise<T, E> {
Promise { node: Box::new(promise_node::Immediate::new(Err(error))) }
}
pub fn never_done() -> Promise<T, E> {
Promise { node: Box::new(promise_node::NeverDone::new()) }
}
pub fn and_fulfiller() -> (Promise<T, E>, PromiseFulfiller<T, E>)
where E: FulfillerDropped
{
let result = Rc::new(RefCell::new(PromiseAndFulfillerHub::new()));
let result_promise: Promise<T, E> =
Promise { node: Box::new(PromiseAndFulfillerWrapper::new(result.clone()))};
(result_promise, PromiseFulfiller{ hub: result, done: false })
}
pub fn then_else<F, T1, E1>(self, func: F) -> Promise<T1, E1>
where F: 'static,
F: FnOnce(Result<T, E>) -> Promise<T1, E1>,
{
let intermediate = Box::new(promise_node::Transform::new(self.node, |x| Ok(func(x)) ));
Promise { node: Box::new(promise_node::Chain::new(intermediate)) }
}
pub fn then<F, T1>(self, func: F) -> Promise<T1, E>
where F: 'static,
F: FnOnce(T) -> Promise<T1, E>,
{
self.then_else(|r| { match r { Ok(v) => func(v), Err(e) => Promise::err(e) } })
}
pub fn map_else<F, T1, E1>(self, func: F) -> Promise<T1, E1>
where F: 'static,
F: FnOnce(Result<T, E>) -> Result<T1, E1>,
{
Promise { node: Box::new(promise_node::Transform::new(self.node, func)) }
}
pub fn map<F, R>(self, func: F) -> Promise<R, E>
where F: 'static,
F: FnOnce(T) -> Result<R, E>,
R: 'static
{
self.map_else(|r| { match r { Ok(v) => func(v), Err(e) => Err(e) } } )
}
pub fn map_err<E1, F>(self, func: F) -> Promise<T, E1>
where F: 'static,
F: FnOnce(E) -> E1
{
self.map_else(|r| { match r { Ok(v) => Ok(v), Err(e) => Err(func(e)) } } )
}
pub fn lift<E1>(self) -> Promise<T, E1> where E: Into<E1> {
self.map_err(|e| e.into())
}
pub fn exclusive_join(self, other: Promise<T, E>) -> Promise<T, E> {
Promise { node: Box::new(private::promise_node::ExclusiveJoin::new(self.node, other.node)) }
}
pub fn all<I>(promises: I) -> Promise<Vec<T>, E>
where I: Iterator<Item=Promise<T, E>>
{
Promise { node: Box::new(private::promise_node::ArrayJoin::new(promises)) }
}
pub fn fork(self) -> ForkedPromise<T, E> where T: Clone, E: Clone {
ForkedPromise::new(self)
}
pub fn attach<U>(self, value: U) -> Promise<T, E> where U: 'static {
self.map_else(move |result| { drop(value); result })
}
pub fn eagerly_evaluate(self) -> Promise<T, E> {
self.then(|v| { Promise::ok(v) })
}
pub fn wait<E1>(mut self, wait_scope: &WaitScope, event_source: &mut EventPort<E1>) -> Result<T, E>
where E: From<E1>
{
drop(wait_scope);
with_current_event_loop(move |event_loop| {
let fired = ::std::rc::Rc::new(::std::cell::Cell::new(false));
let done_event = BoolEvent::new(fired.clone());
let (handle, _dropper) = private::GuardedEventHandle::new();
handle.set(Box::new(done_event));
self.node.on_ready(handle);
while !fired.get() {
if !event_loop.turn() {
try!(event_source.wait());
}
}
self.node.get()
})
}
}
pub struct WaitScope(::std::marker::PhantomData<*mut u8>);
pub struct ForkedPromise<T, E> where T: 'static + Clone, E: 'static + Clone {
hub: Rc<RefCell<promise_node::ForkHub<T, E>>>,
}
impl <T, E> ForkedPromise<T, E> where T: 'static + Clone, E: 'static + Clone {
fn new(inner: Promise<T, E>) -> ForkedPromise<T, E> {
ForkedPromise {
hub: Rc::new(RefCell::new(promise_node::ForkHub::new(inner.node))),
}
}
pub fn add_branch(&mut self) -> Promise<T, E> {
promise_node::ForkHub::add_branch(&self.hub)
}
}
pub trait EventPort<E> {
fn wait(&mut self) -> Result<(), E>;
}
pub struct ClosedEventPort<E: Clone>(pub E);
impl <E: Clone> EventPort<E> for ClosedEventPort<E> {
fn wait(&mut self) -> Result<(), E> {
Err(self.0.clone())
}
}
pub struct EventLoop {
_running: bool,
_last_runnable_state: bool,
events: RefCell<handle_table::HandleTable<private::EventNode>>,
head: private::EventHandle,
tail: Cell<private::EventHandle>,
depth_first_insertion_point: Cell<private::EventHandle>,
currently_firing: Cell<Option<private::EventHandle>>,
to_destroy: Cell<Option<private::EventHandle>>,
}
impl EventLoop {
pub fn top_level<R, F>(main: F) -> R
where F: FnOnce(&WaitScope) -> R,
{
let mut events = handle_table::HandleTable::<private::EventNode>::new();
let dummy = private::EventNode { event: None, next: None, prev: None };
let head_handle = private::EventHandle(events.push(dummy));
EVENT_LOOP.with(move |maybe_event_loop| {
let event_loop = EventLoop {
_running: false,
_last_runnable_state: false,
events: RefCell::new(events),
head: head_handle,
tail: Cell::new(head_handle),
depth_first_insertion_point: Cell::new(head_handle), currently_firing: Cell::new(None),
to_destroy: Cell::new(None),
};
assert!(maybe_event_loop.borrow().is_none());
*maybe_event_loop.borrow_mut() = Some(event_loop);
});
let wait_scope = WaitScope(::std::marker::PhantomData);
let result = main(&wait_scope);
EVENT_LOOP.with(move |maybe_event_loop| {
let el = ::std::mem::replace(&mut *maybe_event_loop.borrow_mut(), None);
match el {
None => unreachable!(),
Some(event_loop) => {
let remaining_events = event_loop.events.borrow().len();
if remaining_events > 1 {
::std::mem::forget(event_loop); panic!("{} leaked events found when cleaning up event loop. \
Perhaps there is a reference cycle containing promises?",
remaining_events - 1)
}
}
}
});
result
}
fn arm_depth_first(&self, event_handle: private::EventHandle) {
let insertion_node_next = self.events.borrow()[self.depth_first_insertion_point.get().0].next;
match insertion_node_next {
Some(next_handle) => {
self.events.borrow_mut()[next_handle.0].prev = Some(event_handle);
self.events.borrow_mut()[event_handle.0].next = Some(next_handle);
}
None => {
self.tail.set(event_handle);
}
}
self.events.borrow_mut()[event_handle.0].prev = Some(self.depth_first_insertion_point.get());
self.events.borrow_mut()[self.depth_first_insertion_point.get().0].next = Some(event_handle);
self.depth_first_insertion_point.set(event_handle);
}
fn arm_breadth_first(&self, event_handle: private::EventHandle) {
let events = &mut *self.events.borrow_mut();
events[self.tail.get().0].next = Some(event_handle);
events[event_handle.0].prev = Some(self.tail.get());
self.tail.set(event_handle);
}
fn _run(&mut self, max_turn_count: u32) {
self._running = true;
for _ in 0..max_turn_count {
if !self.turn() {
break;
}
}
}
fn turn(&self) -> bool {
let event_handle = match self.events.borrow()[self.head.0].next {
None => return false,
Some(event_handle) => { event_handle }
};
self.depth_first_insertion_point.set(event_handle);
self.currently_firing.set(Some(event_handle));
let mut event = ::std::mem::replace(&mut self.events.borrow_mut()[event_handle.0].event, None)
.expect("No event to fire?");
event.fire();
self.currently_firing.set(None);
let maybe_next = self.events.borrow()[event_handle.0].next;
self.events.borrow_mut()[self.head.0].next = maybe_next;
if let Some(e) = maybe_next {
self.events.borrow_mut()[e.0].prev = Some(self.head);
}
self.events.borrow_mut()[event_handle.0].next = None;
self.events.borrow_mut()[event_handle.0].prev = None;
if self.tail.get() == event_handle {
self.tail.set(self.head);
}
self.depth_first_insertion_point.set(self.head);
if let Some(event_handle) = self.to_destroy.get() {
self.events.borrow_mut().remove(event_handle.0);
self.to_destroy.set(None);
}
true
}
}
pub trait FulfillerDropped {
fn fulfiller_dropped() -> Self;
}
pub struct PromiseFulfiller<T, E> where T: 'static, E: 'static + FulfillerDropped {
hub: Rc<RefCell<private::PromiseAndFulfillerHub<T,E>>>,
done: bool,
}
impl <T, E> PromiseFulfiller<T, E> where T: 'static, E: 'static + FulfillerDropped {
pub fn fulfill(mut self, value: T) {
self.hub.borrow_mut().resolve(Ok(value));
self.done = true;
}
pub fn reject(mut self, error: E) {
self.hub.borrow_mut().resolve(Err(error));
self.done = true;
}
pub fn resolve(mut self, result: Result<T, E>) {
self.hub.borrow_mut().resolve(result);
self.done = true;
}
}
impl <T, E> Drop for PromiseFulfiller<T, E> where T: 'static, E: 'static + FulfillerDropped {
fn drop(&mut self) {
if !self.done {
self.hub.borrow_mut().resolve(Err(E::fulfiller_dropped()));
}
}
}
impl FulfillerDropped for () {
fn fulfiller_dropped() -> () { () }
}
impl FulfillerDropped for ::std::io::Error {
fn fulfiller_dropped() -> ::std::io::Error {
::std::io::Error::new(::std::io::ErrorKind::Other, "Promise fulfiller was dropped.")
}
}
pub struct TaskSet<T, E> where T: 'static, E: 'static {
task_set_impl: private::TaskSetImpl<T, E>,
}
impl <T, E> TaskSet <T, E> {
pub fn new(reaper: Box<TaskReaper<T, E>>) -> TaskSet<T, E> {
TaskSet { task_set_impl: private::TaskSetImpl::new(reaper) }
}
pub fn add(&mut self, promise: Promise<T, E>) {
self.task_set_impl.add(promise.node);
}
}
pub trait TaskReaper<T, E> where T: 'static, E: 'static {
fn task_succeeded(&mut self, _value: T) {}
fn task_failed(&mut self, error: E);
}