mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +02:00
Remove the Any bound from LoopData
No need for this, all we need is 'static now
This commit is contained in:
+30
-58
@@ -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>) }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user