Remove the Any bound from LoopData

No need for this, all we need is 'static now
This commit is contained in:
Alex Crichton
2016-08-12 11:15:34 -07:00
parent 0aa7ab94ff
commit ef3efd4175
+30 -58
View File
@@ -1,4 +1,3 @@
use std::any::Any;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::io::{self, ErrorKind}; use std::io::{self, ErrorKind};
use std::marker; use std::marker;
@@ -91,7 +90,7 @@ enum Message {
UpdateTimeout(TimeoutToken, TaskHandle), UpdateTimeout(TimeoutToken, TaskHandle),
CancelTimeout(TimeoutToken), CancelTimeout(TimeoutToken),
Run(Box<ExecuteCallback>), Run(Box<ExecuteCallback>),
Drop(DropBox<Any>), Drop(DropBox<dropbox::MyDrop>),
Shutdown, Shutdown,
} }
@@ -161,7 +160,7 @@ impl Loop {
/// of the underlying `A`. That is, for example, you can create a handle to /// of the underlying `A`. That is, for example, you can create a handle to
/// some data that contains an `Rc`, for example. /// some data that contains an `Rc`, for example.
pub fn add_loop_data<A>(&self, a: A) -> LoopData<A> pub fn add_loop_data<A>(&self, a: A) -> LoopData<A>
where A: Any, where A: 'static,
{ {
LoopData { LoopData {
data: DropBox::new_on(a, self), data: DropBox::new_on(a, self),
@@ -564,7 +563,7 @@ impl LoopHandle {
/// This function takes a closure which may be sent to the event loop to /// This function takes a closure which may be sent to the event loop to
/// generate an instance of type `A`. The closure itself is required to be /// generate an instance of type `A`. The closure itself is required to be
/// `Send + 'static`, but the data it produces is only required to adhere to /// `Send + 'static`, but the data it produces is only required to adhere to
/// `Any`. /// `'static`.
/// ///
/// If the returned future is polled on the event loop thread itself it will /// If the returned future is polled on the event loop thread itself it will
/// very cheaply resolve to a handle to the data, but if it's not polled on /// very cheaply resolve to a handle to the data, but if it's not polled on
@@ -573,10 +572,9 @@ impl LoopHandle {
// TODO: more with examples // TODO: more with examples
pub fn add_loop_data<F, A>(&self, f: F) -> AddLoopData<F, A> pub fn add_loop_data<F, A>(&self, f: F) -> AddLoopData<F, A>
where F: FnOnce() -> A + Send + 'static, where F: FnOnce() -> A + Send + 'static,
A: Any, A: 'static,
{ {
AddLoopData { AddLoopData {
_marker: marker::PhantomData,
inner: LoopFuture { inner: LoopFuture {
loop_handle: self.clone(), loop_handle: self.clone(),
data: Some(f), data: Some(f),
@@ -660,7 +658,7 @@ impl Future for AddTimeout {
/// data originated on, so it knows how to go back to the event loop to access /// data originated on, so it knows how to go back to the event loop to access
/// the data itself. /// the data itself.
// TODO: write more once it's implemented // TODO: write more once it's implemented
pub struct LoopData<A: Any> { pub struct LoopData<A: 'static> {
data: DropBox<A>, data: DropBox<A>,
handle: LoopHandle, handle: LoopHandle,
} }
@@ -671,8 +669,7 @@ pub struct LoopData<A: Any> {
/// represents a handle to data that is "owned" by the event loop thread but can /// represents a handle to data that is "owned" by the event loop thread but can
/// migrate among threads temporarily so travel with a future itself. /// migrate among threads temporarily so travel with a future itself.
pub struct AddLoopData<F, A> { pub struct AddLoopData<F, A> {
inner: LoopFuture<DropBox<Any>, F>, inner: LoopFuture<DropBox<A>, F>,
_marker: marker::PhantomData<fn() -> A>,
} }
fn _assert() { fn _assert() {
@@ -682,7 +679,7 @@ fn _assert() {
impl<F, A> Future for AddLoopData<F, A> impl<F, A> Future for AddLoopData<F, A>
where F: FnOnce() -> A + Send + 'static, where F: FnOnce() -> A + Send + 'static,
A: Any, A: 'static,
{ {
type Item = LoopData<A>; type Item = LoopData<A>;
type Error = io::Error; type Error = io::Error;
@@ -692,15 +689,10 @@ impl<F, A> Future for AddLoopData<F, A>
Ok(DropBox::new(f())) Ok(DropBox::new(f()))
}); });
ret.map(|mut data| { ret.map(|data| {
match data.downcast::<A>() { LoopData {
Some(data) => { data: data,
LoopData { handle: self.inner.loop_handle.clone(),
data: data,
handle: self.inner.loop_handle.clone(),
}
}
None => panic!("data mixed up?"),
} }
}) })
} }
@@ -715,7 +707,7 @@ impl<F, A> Future for AddLoopData<F, A>
} }
} }
impl<A: Any> LoopData<A> { impl<A: 'static> LoopData<A> {
/// Gets a shared reference to the underlying data in this handle. /// Gets a shared reference to the underlying data in this handle.
/// ///
/// Returns `None` if it is not called from the event loop thread that this /// Returns `None` if it is not called from the event loop thread that this
@@ -754,17 +746,17 @@ impl<A: Any> LoopData<A> {
} }
} }
impl<A: Any> Drop for LoopData<A> { impl<A: 'static> Drop for LoopData<A> {
fn drop(&mut self) { fn drop(&mut self) {
// The `DropBox` we store internally will cause a memory leak if it's // The `DropBox` we store internally will cause a memory leak if it's
// dropped on the wrong thread. While necessary for safety, we don't // dropped on the wrong thread. While necessary for safety, we don't
// actually want a memory leak, so for all normal circumstances we take // actually want a memory leak, so for all normal circumstances we take
// out the `DropBox<A>` as a `DropBox<Any>` and then we send it off to // out the `DropBox<A>` as a `DropBox<MyDrop>` and then we send it off
// the event loop. // to the event loop.
// //
// TODO: possible optimization is to do none of this if we're on the // TODO: possible optimization is to do none of this if we're on the
// event loop thread itself // event loop thread itself
if let Some(data) = self.data.take_any() { if let Some(data) = self.data.take() {
self.handle.send(Message::Drop(data)); self.handle.send(Message::Drop(data));
} }
} }
@@ -780,8 +772,8 @@ impl<A: Any> Drop for LoopData<A> {
/// ///
/// A `DropBox` currently contains two major components, an identification of /// A `DropBox` currently contains two major components, an identification of
/// the thread that it originated from as well as the data itself. Right now the /// the thread that it originated from as well as the data itself. Right now the
/// data is stored in a `Box` as we'll transition between it and `Box<Any>`, but /// data is stored in a `Box` as we'll transition between it and `Box<MyDrop>`,
/// this is perhaps optimizable. /// but this is perhaps optimizable.
/// ///
/// The `DropBox<A>` itself only provides a few safe methods, all of which are /// The `DropBox<A>` itself only provides a few safe methods, all of which are
/// safe to call from any thread. Access to the underlying data is only granted /// safe to call from any thread. Access to the underlying data is only granted
@@ -805,7 +797,6 @@ impl<A: Any> Drop for LoopData<A> {
/// itself is quite unsafe as it has to make sure that the data is dropped in /// itself is quite unsafe as it has to make sure that the data is dropped in
/// the right place, if ever. /// the right place, if ever.
mod dropbox { mod dropbox {
use std::any::Any;
use std::mem; use std::mem;
use super::{CURRENT_LOOP, Loop}; use super::{CURRENT_LOOP, Loop};
@@ -821,59 +812,40 @@ mod dropbox {
// reference on at most one thread, regardless of `A`. // reference on at most one thread, regardless of `A`.
unsafe impl<A: ?Sized> Sync for DropBox<A> {} unsafe impl<A: ?Sized> Sync for DropBox<A> {}
impl DropBox<Any> { pub trait MyDrop {}
impl<T: ?Sized> MyDrop for T {}
impl<A> DropBox<A> {
/// Creates a new `DropBox` pinned to the current threads. /// Creates a new `DropBox` pinned to the current threads.
/// ///
/// Will panic if `CURRENT_LOOP` isn't set. /// Will panic if `CURRENT_LOOP` isn't set.
pub fn new<A: Any>(a: A) -> DropBox<Any> { pub fn new(a: A) -> DropBox<A> {
DropBox { DropBox {
id: CURRENT_LOOP.with(|lp| lp.id), id: CURRENT_LOOP.with(|lp| lp.id),
inner: Some(Box::new(a) as Box<Any>), inner: Some(Box::new(a)),
} }
} }
/// Creates a new `DropBox` pinned to the thread of `Loop`. /// Creates a new `DropBox` pinned to the thread of `Loop`.
/// ///
/// Will panic if `CURRENT_LOOP` isn't set. /// Will panic if `CURRENT_LOOP` isn't set.
pub fn new_on<A: Any>(a: A, lp: &Loop) -> DropBox<A> { pub fn new_on(a: A, lp: &Loop) -> DropBox<A> {
DropBox { DropBox {
id: lp.id, id: lp.id,
inner: Some(Box::new(a)), inner: Some(Box::new(a)),
} }
} }
/// Downcasts this `DropBox` to the type specified.
///
/// Normally this always succeeds as it's a static assertion that we
/// already have all the types matched up, but an `Option` is returned
/// here regardless.
pub fn downcast<A: Any>(&mut self) -> Option<DropBox<A>> {
self.inner.take().and_then(|data| {
match data.downcast::<A>() {
Ok(a) => Some(DropBox { id: self.id, inner: Some(a) }),
// Note that we're careful that when a downcast fails we put
// the data back into ourselves, because we may be
// downcasting on any thread. This will ensure that if we
// drop accidentally we'll forget the data correctly.
Err(obj) => {
self.inner = Some(obj);
None
}
}
})
}
}
impl<A: Any> DropBox<A> {
/// Consumes the contents of this `DropBox<A>`, returning a new /// Consumes the contents of this `DropBox<A>`, returning a new
/// `DropBox<Any>`. /// `DropBox<MyDrop>`.
/// ///
/// This is just intended to be a simple and cheap conversion, should /// This is just intended to be a simple and cheap conversion, should
/// almost always return `Some`. /// almost always return `Some`.
pub fn take_any(&mut self) -> Option<DropBox<Any>> { pub fn take<'a>(&mut self) -> Option<DropBox<MyDrop + 'a>>
where A: 'a
{
self.inner.take().map(|d| { self.inner.take().map(|d| {
DropBox { id: self.id, inner: Some(d as Box<Any>) } DropBox { id: self.id, inner: Some(d as Box<MyDrop + 'a>) }
}) })
} }
} }