mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-17 00:00:11 +02:00
`inner` is a fitting name for variables of type named `Inner`, but in other cases I find them confusing - sometimes `inner` refers to a `Pool`, sometimes to a `Sender`. I renamed a bunch of variables named `inner` to be more descriptive. This PR is the first step in an effort of splitting https://github.com/tokio-rs/tokio/pull/722#issuecomment-439552671 into multiple PRs.
93 lines
2.4 KiB
Rust
93 lines
2.4 KiB
Rust
use pool::Pool;
|
|
use task::Task;
|
|
|
|
use std::mem;
|
|
use std::ops;
|
|
use std::sync::Arc;
|
|
|
|
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 {
|
|
pub pool: Arc<Pool>,
|
|
}
|
|
|
|
/// A guard that ensures that the inner value gets forgotten.
|
|
#[derive(Debug)]
|
|
struct Forget<T>(Option<T>);
|
|
|
|
impl Notify for Notifier {
|
|
fn notify(&self, id: usize) {
|
|
trace!("Notifier::notify; id=0x{:x}", id);
|
|
|
|
unsafe {
|
|
let ptr = id as *const Task;
|
|
|
|
// We did not actually take ownership of the `Arc` in this function
|
|
// so we must ensure that the Arc is forgotten.
|
|
let task = Forget::new(Arc::from_raw(ptr));
|
|
|
|
// TODO: Unify this with Task::notify
|
|
if task.schedule() {
|
|
// TODO: Check if the pool is still running
|
|
//
|
|
// Bump the ref count
|
|
let task = task.clone();
|
|
|
|
let _ = self.pool.submit(task, &self.pool);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn clone_id(&self, id: usize) -> usize {
|
|
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 = Forget::new(unsafe { Arc::from_raw(ptr) });
|
|
|
|
// The clone 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.
|
|
let _ = Forget::new(t1.clone());
|
|
|
|
id
|
|
}
|
|
|
|
fn drop_id(&self, id: usize) {
|
|
unsafe {
|
|
let ptr = id as *const Task;
|
|
let _ = Arc::from_raw(ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ===== impl Forget =====
|
|
|
|
impl<T> Forget<T> {
|
|
fn new(t: T) -> Self {
|
|
Forget(Some(t))
|
|
}
|
|
}
|
|
|
|
impl<T> ops::Deref for Forget<T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &T {
|
|
self.0.as_ref().unwrap()
|
|
}
|
|
}
|
|
|
|
impl<T> Drop for Forget<T> {
|
|
fn drop(&mut self) {
|
|
mem::forget(self.0.take());
|
|
}
|
|
}
|