mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-24 00:00:11 +02:00
Refactor threadpool task types (#300)
Replaces homegrown Arc with std Arc Is this safer? Unknown. At least we don't have to maintain an arc implementation anymore. This will also make it easier to filter out tsan false positives. Also split task/mod.rs into multiple files.
This commit is contained in:
@@ -2,7 +2,7 @@ use pool::Pool;
|
||||
use task::Task;
|
||||
|
||||
use std::mem;
|
||||
use std::sync::Weak;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use futures::executor::Notify;
|
||||
|
||||
@@ -19,37 +19,51 @@ impl Notify for Notifier {
|
||||
fn notify(&self, id: usize) {
|
||||
trace!("Notifier::notify; id=0x{:x}", id);
|
||||
|
||||
let id = id as usize;
|
||||
let task = unsafe { Task::from_notify_id_ref(&id) };
|
||||
unsafe {
|
||||
let ptr = id as *const Task;
|
||||
let task = Arc::from_raw(ptr);
|
||||
|
||||
if !task.schedule() {
|
||||
trace!(" -> task already scheduled");
|
||||
// task is already scheduled, there is nothing more to do
|
||||
return;
|
||||
}
|
||||
if task.schedule() {
|
||||
// TODO: Check if the pool is still running
|
||||
//
|
||||
// Bump the ref count
|
||||
let task = task.clone();
|
||||
|
||||
// TODO: Check if the pool is still running
|
||||
if let Some(inner) = self.inner.upgrade() {
|
||||
let _ = inner.submit(task, &inner);
|
||||
}
|
||||
}
|
||||
|
||||
// Bump the ref count
|
||||
let task = task.clone();
|
||||
|
||||
if let Some(inner) = self.inner.upgrade() {
|
||||
let _ = inner.submit(task, &inner);
|
||||
// We did not actually take ownership of the `Arc` in this function.
|
||||
mem::forget(task);
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_id(&self, id: usize) -> usize {
|
||||
unsafe {
|
||||
let handle = Task::from_notify_id_ref(&id);
|
||||
mem::forget(handle.clone());
|
||||
}
|
||||
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);
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
fn drop_id(&self, id: usize) {
|
||||
unsafe {
|
||||
let _ = Task::from_notify_id(id);
|
||||
let ptr = id as *const Task;
|
||||
let _ = Arc::from_raw(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user