diff --git a/src/event_loop.rs b/src/event_loop.rs index 9e46523db..baaf526b1 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -1,4 +1,3 @@ -use std::any::Any; use std::cell::{Cell, RefCell}; use std::io::{self, ErrorKind}; use std::marker; @@ -91,7 +90,7 @@ enum Message { UpdateTimeout(TimeoutToken, TaskHandle), CancelTimeout(TimeoutToken), Run(Box), - Drop(DropBox), + Drop(DropBox), Shutdown, } @@ -161,7 +160,7 @@ impl Loop { /// of the underlying `A`. That is, for example, you can create a handle to /// some data that contains an `Rc`, for example. pub fn add_loop_data(&self, a: A) -> LoopData - where A: Any, + where A: 'static, { LoopData { 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 /// 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 - /// `Any`. + /// `'static`. /// /// 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 @@ -573,10 +572,9 @@ impl LoopHandle { // TODO: more with examples pub fn add_loop_data(&self, f: F) -> AddLoopData where F: FnOnce() -> A + Send + 'static, - A: Any, + A: 'static, { AddLoopData { - _marker: marker::PhantomData, inner: LoopFuture { loop_handle: self.clone(), 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 /// the data itself. // TODO: write more once it's implemented -pub struct LoopData { +pub struct LoopData { data: DropBox, handle: LoopHandle, } @@ -671,8 +669,7 @@ pub struct LoopData { /// 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. pub struct AddLoopData { - inner: LoopFuture, F>, - _marker: marker::PhantomData A>, + inner: LoopFuture, F>, } fn _assert() { @@ -682,7 +679,7 @@ fn _assert() { impl Future for AddLoopData where F: FnOnce() -> A + Send + 'static, - A: Any, + A: 'static, { type Item = LoopData; type Error = io::Error; @@ -692,15 +689,10 @@ impl Future for AddLoopData Ok(DropBox::new(f())) }); - ret.map(|mut data| { - match data.downcast::() { - Some(data) => { - LoopData { - data: data, - handle: self.inner.loop_handle.clone(), - } - } - None => panic!("data mixed up?"), + ret.map(|data| { + LoopData { + data: data, + handle: self.inner.loop_handle.clone(), } }) } @@ -715,7 +707,7 @@ impl Future for AddLoopData } } -impl LoopData { +impl LoopData { /// 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 @@ -754,17 +746,17 @@ impl LoopData { } } -impl Drop for LoopData { +impl Drop for LoopData { fn drop(&mut self) { // 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 // actually want a memory leak, so for all normal circumstances we take - // out the `DropBox` as a `DropBox` and then we send it off to - // the event loop. + // out the `DropBox` as a `DropBox` and then we send it off + // to the event loop. // // TODO: possible optimization is to do none of this if we're on the // 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)); } } @@ -780,8 +772,8 @@ impl Drop for LoopData { /// /// 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 -/// data is stored in a `Box` as we'll transition between it and `Box`, but -/// this is perhaps optimizable. +/// data is stored in a `Box` as we'll transition between it and `Box`, +/// but this is perhaps optimizable. /// /// The `DropBox` 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 @@ -805,7 +797,6 @@ impl Drop for LoopData { /// itself is quite unsafe as it has to make sure that the data is dropped in /// the right place, if ever. mod dropbox { - use std::any::Any; use std::mem; use super::{CURRENT_LOOP, Loop}; @@ -821,59 +812,40 @@ mod dropbox { // reference on at most one thread, regardless of `A`. unsafe impl Sync for DropBox {} - impl DropBox { + pub trait MyDrop {} + impl MyDrop for T {} + + impl DropBox { /// Creates a new `DropBox` pinned to the current threads. /// /// Will panic if `CURRENT_LOOP` isn't set. - pub fn new(a: A) -> DropBox { + pub fn new(a: A) -> DropBox { DropBox { id: CURRENT_LOOP.with(|lp| lp.id), - inner: Some(Box::new(a) as Box), + inner: Some(Box::new(a)), } } /// Creates a new `DropBox` pinned to the thread of `Loop`. /// /// Will panic if `CURRENT_LOOP` isn't set. - pub fn new_on(a: A, lp: &Loop) -> DropBox { + pub fn new_on(a: A, lp: &Loop) -> DropBox { DropBox { id: lp.id, 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(&mut self) -> Option> { - self.inner.take().and_then(|data| { - match data.downcast::() { - 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 DropBox { /// Consumes the contents of this `DropBox`, returning a new - /// `DropBox`. + /// `DropBox`. /// /// This is just intended to be a simple and cheap conversion, should /// almost always return `Some`. - pub fn take_any(&mut self) -> Option> { + pub fn take<'a>(&mut self) -> Option> + where A: 'a + { self.inner.take().map(|d| { - DropBox { id: self.id, inner: Some(d as Box) } + DropBox { id: self.id, inner: Some(d as Box) } }) } }