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:
Carl Lerche
2018-04-05 10:57:05 -07:00
committed by GitHub
parent 0bcf9b0ae6
commit 3be6b69e1b
9 changed files with 479 additions and 546 deletions
+33 -19
View File
@@ -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);
}
}
}