mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-28 12:10:37 +00:00
Add a method to add data to an event loop directly
Avoids Send entirely
This commit is contained in:
parent
8daac0347d
commit
164193fe82
@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell};
|
||||
use std::io::{self, ErrorKind};
|
||||
use std::marker;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
use std::sync::mpsc;
|
||||
@ -47,6 +48,12 @@ pub struct Loop {
|
||||
// `timeouts` slab.
|
||||
timer_wheel: RefCell<TimerWheel<usize>>,
|
||||
timeouts: RefCell<Slab<(Timeout, TimeoutState), usize>>,
|
||||
|
||||
// A `Loop` cannot be sent to other threads as it's used as a proxy for data
|
||||
// that belongs to the thread the loop was running on at some point. In
|
||||
// other words, the safety of `DropBox` below relies on loops not crossing
|
||||
// threads.
|
||||
_marker: marker::PhantomData<Rc<u32>>,
|
||||
}
|
||||
|
||||
struct MioSender {
|
||||
@ -128,6 +135,7 @@ impl Loop {
|
||||
dispatch: RefCell::new(Slab::new_starting_at(1, SLAB_CAPACITY)),
|
||||
timeouts: RefCell::new(Slab::new_starting_at(0, SLAB_CAPACITY)),
|
||||
timer_wheel: RefCell::new(TimerWheel::new()),
|
||||
_marker: marker::PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
@ -143,6 +151,22 @@ impl Loop {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `LoopData<A>` handle by associating data to be directly
|
||||
/// stored by this event loop.
|
||||
///
|
||||
/// This function is useful for when storing non-`Send` data inside of a
|
||||
/// future. The `LoopData<A>` handle is itself `Send + 'static` regardless
|
||||
/// 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<A>(&self, a: A) -> LoopData<A>
|
||||
where A: Any,
|
||||
{
|
||||
LoopData {
|
||||
data: DropBox::new_on(a, self),
|
||||
handle: self.handle(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs a future until completion, driving the event loop while we're
|
||||
/// otherwise waiting for the future to complete.
|
||||
///
|
||||
@ -776,7 +800,7 @@ impl<A: Any> Drop for LoopData<A> {
|
||||
mod dropbox {
|
||||
use std::any::Any;
|
||||
use std::mem;
|
||||
use super::CURRENT_LOOP;
|
||||
use super::{CURRENT_LOOP, Loop};
|
||||
|
||||
pub struct DropBox<A: ?Sized> {
|
||||
id: usize,
|
||||
@ -801,6 +825,16 @@ mod dropbox {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `DropBox` pinned to the thread of `Loop`.
|
||||
///
|
||||
/// Will panic if `CURRENT_LOOP` isn't set.
|
||||
pub fn new_on<A: Any>(a: A, lp: &Loop) -> DropBox<A> {
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user