Skip to content

Commit 3c7187b

Browse files
dbcfdjensim
authored andcommitted
io: add mio::Ready argument to PollEvented (tokio-rs#2419)
Add additional methods to allow PollEvented to be created with an appropriate mio::Ready state, so that it can be properly registered with the reactor. Fixes tokio-rs#2413
1 parent bae8754 commit 3c7187b

File tree

3 files changed

+81
-12
lines changed

3 files changed

+81
-12
lines changed

tokio/src/io/driver/mod.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,14 @@ impl fmt::Debug for Handle {
237237
// ===== impl Inner =====
238238

239239
impl Inner {
240-
/// Registers an I/O resource with the reactor.
240+
/// Registers an I/O resource with the reactor for a given `mio::Ready` state.
241241
///
242242
/// The registration token is returned.
243-
pub(super) fn add_source(&self, source: &dyn Evented) -> io::Result<Address> {
243+
pub(super) fn add_source(
244+
&self,
245+
source: &dyn Evented,
246+
ready: mio::Ready,
247+
) -> io::Result<Address> {
244248
let address = self.io_dispatch.alloc().ok_or_else(|| {
245249
io::Error::new(
246250
io::ErrorKind::Other,
@@ -253,7 +257,7 @@ impl Inner {
253257
self.io.register(
254258
source,
255259
mio::Token(address.to_usize()),
256-
mio::Ready::all(),
260+
ready,
257261
mio::PollOpt::edge(),
258262
)?;
259263

@@ -339,12 +343,12 @@ mod tests {
339343
let inner = reactor.inner;
340344
let inner2 = inner.clone();
341345

342-
let token_1 = inner.add_source(&NotEvented).unwrap();
346+
let token_1 = inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
343347
let thread = thread::spawn(move || {
344348
inner2.drop_source(token_1);
345349
});
346350

347-
let token_2 = inner.add_source(&NotEvented).unwrap();
351+
let token_2 = inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
348352
thread.join().unwrap();
349353

350354
assert!(token_1 != token_2);
@@ -360,15 +364,15 @@ mod tests {
360364
// add sources to fill up the first page so that the dropped index
361365
// may be reused.
362366
for _ in 0..31 {
363-
inner.add_source(&NotEvented).unwrap();
367+
inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
364368
}
365369

366-
let token_1 = inner.add_source(&NotEvented).unwrap();
370+
let token_1 = inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
367371
let thread = thread::spawn(move || {
368372
inner2.drop_source(token_1);
369373
});
370374

371-
let token_2 = inner.add_source(&NotEvented).unwrap();
375+
let token_2 = inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
372376
thread.join().unwrap();
373377

374378
assert!(token_1 != token_2);
@@ -383,11 +387,11 @@ mod tests {
383387
let inner2 = inner.clone();
384388

385389
let thread = thread::spawn(move || {
386-
let token_2 = inner2.add_source(&NotEvented).unwrap();
390+
let token_2 = inner2.add_source(&NotEvented, mio::Ready::all()).unwrap();
387391
token_2
388392
});
389393

390-
let token_1 = inner.add_source(&NotEvented).unwrap();
394+
let token_1 = inner.add_source(&NotEvented, mio::Ready::all()).unwrap();
391395
let token_2 = thread.join().unwrap();
392396

393397
assert!(token_1 != token_2);

tokio/src/io/poll_evented.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,35 @@ where
175175
/// from a future driven by a tokio runtime, otherwise runtime can be set
176176
/// explicitly with [`Handle::enter`](crate::runtime::Handle::enter) function.
177177
pub fn new(io: E) -> io::Result<Self> {
178-
let registration = Registration::new(&io)?;
178+
PollEvented::new_with_ready(io, mio::Ready::all())
179+
}
180+
181+
/// Creates a new `PollEvented` associated with the default reactor, for specific `mio::Ready`
182+
/// state. `new_with_ready` should be used over `new` when you need control over the readiness
183+
/// state, such as when a file descriptor only allows reads. This does not add `hup` or `error`
184+
/// so if you are interested in those states, you will need to add them to the readiness state
185+
/// passed to this function.
186+
///
187+
/// An example to listen to read only
188+
///
189+
/// ```rust
190+
/// ##[cfg(unix)]
191+
/// mio::Ready::from_usize(
192+
/// mio::Ready::readable().as_usize()
193+
/// | mio::unix::UnixReady::error().as_usize()
194+
/// | mio::unix::UnixReady::hup().as_usize()
195+
/// );
196+
/// ```
197+
///
198+
/// # Panics
199+
///
200+
/// This function panics if thread-local runtime is not set.
201+
///
202+
/// The runtime is usually set implicitly when this function is called
203+
/// from a future driven by a tokio runtime, otherwise runtime can be set
204+
/// explicitly with [`Handle::enter`](crate::runtime::Handle::enter) function.
205+
pub fn new_with_ready(io: E, ready: mio::Ready) -> io::Result<Self> {
206+
let registration = Registration::new_with_ready(&io, ready)?;
179207
Ok(Self {
180208
io: Some(io),
181209
inner: Inner {

tokio/src/io/registration.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,49 @@ impl Registration {
6363
/// from a future driven by a tokio runtime, otherwise runtime can be set
6464
/// explicitly with [`Handle::enter`](crate::runtime::Handle::enter) function.
6565
pub fn new<T>(io: &T) -> io::Result<Registration>
66+
where
67+
T: Evented,
68+
{
69+
Registration::new_with_ready(io, mio::Ready::all())
70+
}
71+
72+
/// Registers the I/O resource with the default reactor, for a specific `mio::Ready` state.
73+
/// `new_with_ready` should be used over `new` when you need control over the readiness state,
74+
/// such as when a file descriptor only allows reads. This does not add `hup` or `error` so if
75+
/// you are interested in those states, you will need to add them to the readiness state passed
76+
/// to this function.
77+
///
78+
/// An example to listen to read only
79+
///
80+
/// ```rust
81+
/// ##[cfg(unix)]
82+
/// mio::Ready::from_usize(
83+
/// mio::Ready::readable().as_usize()
84+
/// | mio::unix::UnixReady::error().as_usize()
85+
/// | mio::unix::UnixReady::hup().as_usize()
86+
/// );
87+
/// ```
88+
///
89+
/// # Return
90+
///
91+
/// - `Ok` if the registration happened successfully
92+
/// - `Err` if an error was encountered during registration
93+
///
94+
///
95+
/// # Panics
96+
///
97+
/// This function panics if thread-local runtime is not set.
98+
///
99+
/// The runtime is usually set implicitly when this function is called
100+
/// from a future driven by a tokio runtime, otherwise runtime can be set
101+
/// explicitly with [`Handle::enter`](crate::runtime::Handle::enter) function.
102+
pub fn new_with_ready<T>(io: &T, ready: mio::Ready) -> io::Result<Registration>
66103
where
67104
T: Evented,
68105
{
69106
let handle = Handle::current();
70107
let address = if let Some(inner) = handle.inner() {
71-
inner.add_source(io)?
108+
inner.add_source(io, ready)?
72109
} else {
73110
return Err(io::Error::new(
74111
io::ErrorKind::Other,

0 commit comments

Comments
 (0)