2018-04-04 13:30:54 -07:00
|
|
|
use pool::Pool;
|
2018-03-28 01:56:21 +03:00
|
|
|
use task::Task;
|
|
|
|
|
|
|
|
|
|
use std::mem;
|
2018-04-05 10:57:05 -07:00
|
|
|
use std::sync::{Arc, Weak};
|
2018-03-28 01:56:21 +03:00
|
|
|
|
|
|
|
|
use futures::executor::Notify;
|
|
|
|
|
|
|
|
|
|
/// Implements the future `Notify` API.
|
|
|
|
|
///
|
|
|
|
|
/// This is how external events are able to signal the task, informing it to try
|
|
|
|
|
/// to poll the future again.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub(crate) struct Notifier {
|
2018-04-04 13:30:54 -07:00
|
|
|
pub inner: Weak<Pool>,
|
2018-03-28 01:56:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Notify for Notifier {
|
|
|
|
|
fn notify(&self, id: usize) {
|
|
|
|
|
trace!("Notifier::notify; id=0x{:x}", id);
|
|
|
|
|
|
2018-04-05 10:57:05 -07:00
|
|
|
unsafe {
|
|
|
|
|
let ptr = id as *const Task;
|
|
|
|
|
let task = Arc::from_raw(ptr);
|
2018-03-28 01:56:21 +03:00
|
|
|
|
2018-04-05 10:57:05 -07:00
|
|
|
if task.schedule() {
|
|
|
|
|
// TODO: Check if the pool is still running
|
|
|
|
|
//
|
|
|
|
|
// Bump the ref count
|
|
|
|
|
let task = task.clone();
|
2018-03-28 01:56:21 +03:00
|
|
|
|
2018-04-05 10:57:05 -07:00
|
|
|
if let Some(inner) = self.inner.upgrade() {
|
|
|
|
|
let _ = inner.submit(task, &inner);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-28 01:56:21 +03:00
|
|
|
|
2018-04-05 10:57:05 -07:00
|
|
|
// We did not actually take ownership of the `Arc` in this function.
|
|
|
|
|
mem::forget(task);
|
2018-03-28 01:56:21 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clone_id(&self, id: usize) -> usize {
|
2018-04-05 10:57:05 -07:00
|
|
|
let ptr = id as *const Task;
|
|
|
|
|
|
|
|
|
|
// This function doesn't actually get a strong ref to the task here.
|
|
|
|
|
// However, the only method we have to convert a raw pointer -> &Arc<T>
|
|
|
|
|
// is to call `Arc::from_raw` which returns a strong ref. So, to
|
|
|
|
|
// maintain the invariants, `t1` has to be forgotten. This prevents the
|
|
|
|
|
// ref count from being decremented.
|
|
|
|
|
let t1 = unsafe { Arc::from_raw(ptr) };
|
|
|
|
|
let t2 = t1.clone();
|
|
|
|
|
|
|
|
|
|
mem::forget(t1);
|
|
|
|
|
|
|
|
|
|
// t2 is forgotten so that the fn exits without decrementing the ref
|
|
|
|
|
// count. The caller of `clone_id` ensures that `drop_id` is called when
|
|
|
|
|
// the ref count needs to be decremented.
|
|
|
|
|
mem::forget(t2);
|
2018-03-28 01:56:21 +03:00
|
|
|
|
|
|
|
|
id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn drop_id(&self, id: usize) {
|
|
|
|
|
unsafe {
|
2018-04-05 10:57:05 -07:00
|
|
|
let ptr = id as *const Task;
|
|
|
|
|
let _ = Arc::from_raw(ptr);
|
2018-03-28 01:56:21 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|