Skip to content

Commit 9ce4e61

Browse files
committed
Refactor IO registration using intrusive linked list
1 parent be7462e commit 9ce4e61

30 files changed

+755
-1307
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ jobs:
150150
run: cargo install cargo-hack
151151

152152
- name: check --each-feature
153-
run: cargo hack check --all --each-feature -Z avoid-dev-deps
153+
run: cargo hack check --all --each-feature --skip io-driver -Z avoid-dev-deps
154154

155155
# Try with unstable feature flags
156156
- name: check --each-feature --unstable
157-
run: cargo hack check --all --each-feature -Z avoid-dev-deps
157+
run: cargo hack check --all --each-feature --skip io-driver -Z avoid-dev-deps
158158
env:
159159
RUSTFLAGS: --cfg tokio_unstable
160160

tokio-util/Cargo.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ publish = false
2525
default = []
2626

2727
# Shorthand for enabling everything
28-
full = ["codec", "udp", "compat", "io"]
28+
full = ["codec", "compat", "io"]
2929

3030
compat = ["futures-io",]
3131
codec = ["tokio/stream"]
32-
udp = ["tokio/udp"]
3332
io = []
3433

3534
[dependencies]

tokio-util/src/cfg.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ macro_rules! cfg_compat {
1818
}
1919
}
2020

21+
/*
2122
macro_rules! cfg_udp {
2223
($($item:item)*) => {
2324
$(
@@ -27,6 +28,7 @@ macro_rules! cfg_udp {
2728
)*
2829
}
2930
}
31+
*/
3032

3133
macro_rules! cfg_io {
3234
($($item:item)*) => {

tokio-util/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,14 @@ cfg_codec! {
3030
pub mod codec;
3131
}
3232

33+
/*
34+
Disabled due to removal of poll_ functions on UdpSocket.
35+
36+
See https://github.com/tokio-rs/tokio/issues/2830
3337
cfg_udp! {
3438
pub mod udp;
3539
}
40+
*/
3641

3742
cfg_compat! {
3843
pub mod compat;

tokio-util/tests/udp.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/*
12
#![warn(rust_2018_idioms)]
23
34
use tokio::{net::UdpSocket, stream::StreamExt};
@@ -100,3 +101,4 @@ async fn send_framed_lines_codec() -> std::io::Result<()> {
100101
101102
Ok(())
102103
}
104+
*/

tokio/src/io/driver/mod.rs

+19-38
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ use mio::event::Evented;
1212
use std::fmt;
1313
use std::io;
1414
use std::sync::{Arc, Weak};
15-
use std::task::Waker;
1615
use std::time::Duration;
1716

1817
/// I/O driver, backed by Mio
1918
pub(crate) struct Driver {
2019
/// Tracks the number of times `turn` is called. It is safe for this to wrap
2120
/// as it is mostly used to determine when to call `compact()`
22-
tick: u16,
21+
tick: u8,
2322

2423
/// Reuse the `mio::Events` value across calls to poll.
2524
events: Option<mio::Events>,
@@ -40,6 +39,11 @@ pub(crate) struct Handle {
4039
inner: Weak<Inner>,
4140
}
4241

42+
pub(crate) struct ReadyEvent {
43+
tick: u8,
44+
readiness: mio::Ready,
45+
}
46+
4347
pub(super) struct Inner {
4448
/// The underlying system event queue.
4549
io: mio::Poll,
@@ -57,6 +61,11 @@ pub(super) enum Direction {
5761
Write,
5862
}
5963

64+
enum Tick {
65+
Set(u8),
66+
Clear(u8),
67+
}
68+
6069
// TODO: Don't use a fake token. Instead, reserve a slot entry for the wakeup
6170
// token.
6271
const TOKEN_WAKEUP: mio::Token = mio::Token(1 << 31);
@@ -122,11 +131,11 @@ impl Driver {
122131

123132
fn turn(&mut self, max_wait: Option<Duration>) -> io::Result<()> {
124133
// How often to call `compact()` on the resource slab
125-
const COMPACT_INTERVAL: u16 = 256;
134+
const COMPACT_INTERVAL: u8 = 255;
126135

127136
self.tick = self.tick.wrapping_add(1);
128137

129-
if self.tick % COMPACT_INTERVAL == 0 {
138+
if self.tick == COMPACT_INTERVAL {
130139
self.resources.compact();
131140
}
132141

@@ -160,39 +169,22 @@ impl Driver {
160169
}
161170

162171
fn dispatch(&mut self, token: mio::Token, ready: mio::Ready) {
163-
let mut rd = None;
164-
let mut wr = None;
165-
166172
let addr = slab::Address::from_usize(ADDRESS.unpack(token.0));
167173

168174
let io = match self.resources.get(addr) {
169175
Some(io) => io,
170176
None => return,
171177
};
172178

173-
if io
174-
.set_readiness(Some(token.0), |curr| curr | ready.as_usize())
175-
.is_err()
176-
{
179+
let set = io.set_readiness(Some(token.0), Tick::Set(self.tick), |curr| {
180+
curr | ready.as_usize()
181+
});
182+
if set.is_err() {
177183
// token no longer valid!
178184
return;
179185
}
180186

181-
if ready.is_writable() || platform::is_hup(ready) || platform::is_error(ready) {
182-
wr = io.writer.take_waker();
183-
}
184-
185-
if !(ready & (!mio::Ready::writable())).is_empty() {
186-
rd = io.reader.take_waker();
187-
}
188-
189-
if let Some(w) = rd {
190-
w.wake();
191-
}
192-
193-
if let Some(w) = wr {
194-
w.wake();
195-
}
187+
io.wake(ready);
196188
}
197189
}
198190

@@ -202,8 +194,7 @@ impl Drop for Driver {
202194
// If a task is waiting on the I/O resource, notify it. The task
203195
// will then attempt to use the I/O resource and fail due to the
204196
// driver being shutdown.
205-
io.reader.wake();
206-
io.writer.wake();
197+
io.wake(mio::Ready::all());
207198
})
208199
}
209200
}
@@ -310,16 +301,6 @@ impl Inner {
310301
pub(super) fn deregister_source(&self, source: &dyn Evented) -> io::Result<()> {
311302
self.io.deregister(source)
312303
}
313-
314-
/// Registers interest in the I/O resource associated with `token`.
315-
pub(super) fn register(&self, io: &slab::Ref<ScheduledIo>, dir: Direction, w: Waker) {
316-
let waker = match dir {
317-
Direction::Read => &io.reader,
318-
Direction::Write => &io.writer,
319-
};
320-
321-
waker.register(w);
322-
}
323304
}
324305

325306
impl Direction {

0 commit comments

Comments
 (0)