1 //! Abstracts out the entire chain of runtime sub-drivers into common types. 2 3 // Eventually, this file will see significant refactoring / cleanup. For now, we 4 // don't need to worry much about dead code with certain feature permutations. 5 #![cfg_attr( 6 any(not(all(tokio_unstable, feature = "full")), target_family = "wasm"), 7 allow(dead_code) 8 )] 9 10 use crate::runtime::park::{ParkThread, UnparkThread}; 11 12 use std::io; 13 use std::time::Duration; 14 15 #[derive(Debug)] 16 pub(crate) struct Driver { 17 inner: TimeDriver, 18 } 19 20 #[derive(Debug)] 21 pub(crate) struct Handle { 22 /// IO driver handle 23 pub(crate) io: IoHandle, 24 25 /// Signal driver handle 26 #[cfg_attr(any(not(unix), loom), allow(dead_code))] 27 pub(crate) signal: SignalHandle, 28 29 /// Time driver handle 30 pub(crate) time: TimeHandle, 31 32 /// Source of `Instant::now()` 33 #[cfg_attr(not(all(feature = "time", feature = "test-util")), allow(dead_code))] 34 pub(crate) clock: Clock, 35 } 36 37 pub(crate) struct Cfg { 38 pub(crate) enable_io: bool, 39 pub(crate) enable_time: bool, 40 pub(crate) enable_pause_time: bool, 41 pub(crate) start_paused: bool, 42 pub(crate) nevents: usize, 43 } 44 45 impl Driver { new(cfg: Cfg) -> io::Result<(Self, Handle)>46 pub(crate) fn new(cfg: Cfg) -> io::Result<(Self, Handle)> { 47 let (io_stack, io_handle, signal_handle) = create_io_stack(cfg.enable_io, cfg.nevents)?; 48 49 let clock = create_clock(cfg.enable_pause_time, cfg.start_paused); 50 51 let (time_driver, time_handle) = create_time_driver(cfg.enable_time, io_stack, &clock); 52 53 Ok(( 54 Self { inner: time_driver }, 55 Handle { 56 io: io_handle, 57 signal: signal_handle, 58 time: time_handle, 59 clock, 60 }, 61 )) 62 } 63 is_enabled(&self) -> bool64 pub(crate) fn is_enabled(&self) -> bool { 65 self.inner.is_enabled() 66 } 67 park(&mut self, handle: &Handle)68 pub(crate) fn park(&mut self, handle: &Handle) { 69 self.inner.park(handle) 70 } 71 park_timeout(&mut self, handle: &Handle, duration: Duration)72 pub(crate) fn park_timeout(&mut self, handle: &Handle, duration: Duration) { 73 self.inner.park_timeout(handle, duration) 74 } 75 shutdown(&mut self, handle: &Handle)76 pub(crate) fn shutdown(&mut self, handle: &Handle) { 77 self.inner.shutdown(handle) 78 } 79 } 80 81 impl Handle { unpark(&self)82 pub(crate) fn unpark(&self) { 83 #[cfg(feature = "time")] 84 if let Some(handle) = &self.time { 85 handle.unpark(); 86 } 87 88 self.io.unpark(); 89 } 90 91 cfg_io_driver! { 92 #[track_caller] 93 pub(crate) fn io(&self) -> &crate::runtime::io::Handle { 94 self.io 95 .as_ref() 96 .expect("A Tokio 1.x context was found, but IO is disabled. Call `enable_io` on the runtime builder to enable IO.") 97 } 98 } 99 100 cfg_signal_internal_and_unix! { 101 #[track_caller] 102 pub(crate) fn signal(&self) -> &crate::runtime::signal::Handle { 103 self.signal 104 .as_ref() 105 .expect("there is no signal driver running, must be called from the context of Tokio runtime") 106 } 107 } 108 109 cfg_time! { 110 /// Returns a reference to the time driver handle. 111 /// 112 /// Panics if no time driver is present. 113 #[track_caller] 114 pub(crate) fn time(&self) -> &crate::runtime::time::Handle { 115 self.time 116 .as_ref() 117 .expect("A Tokio 1.x context was found, but timers are disabled. Call `enable_time` on the runtime builder to enable timers.") 118 } 119 120 pub(crate) fn clock(&self) -> &Clock { 121 &self.clock 122 } 123 } 124 } 125 126 // ===== io driver ===== 127 128 cfg_io_driver! { 129 pub(crate) type IoDriver = crate::runtime::io::Driver; 130 131 #[derive(Debug)] 132 pub(crate) enum IoStack { 133 Enabled(ProcessDriver), 134 Disabled(ParkThread), 135 } 136 137 #[derive(Debug)] 138 pub(crate) enum IoHandle { 139 Enabled(crate::runtime::io::Handle), 140 Disabled(UnparkThread), 141 } 142 143 fn create_io_stack(enabled: bool, nevents: usize) -> io::Result<(IoStack, IoHandle, SignalHandle)> { 144 #[cfg(loom)] 145 assert!(!enabled); 146 147 let ret = if enabled { 148 let (io_driver, io_handle) = crate::runtime::io::Driver::new(nevents)?; 149 150 let (signal_driver, signal_handle) = create_signal_driver(io_driver, &io_handle)?; 151 let process_driver = create_process_driver(signal_driver); 152 153 (IoStack::Enabled(process_driver), IoHandle::Enabled(io_handle), signal_handle) 154 } else { 155 let park_thread = ParkThread::new(); 156 let unpark_thread = park_thread.unpark(); 157 (IoStack::Disabled(park_thread), IoHandle::Disabled(unpark_thread), Default::default()) 158 }; 159 160 Ok(ret) 161 } 162 163 impl IoStack { 164 pub(crate) fn is_enabled(&self) -> bool { 165 match self { 166 IoStack::Enabled(..) => true, 167 IoStack::Disabled(..) => false, 168 } 169 } 170 171 pub(crate) fn park(&mut self, handle: &Handle) { 172 match self { 173 IoStack::Enabled(v) => v.park(handle), 174 IoStack::Disabled(v) => v.park(), 175 } 176 } 177 178 pub(crate) fn park_timeout(&mut self, handle: &Handle, duration: Duration) { 179 match self { 180 IoStack::Enabled(v) => v.park_timeout(handle, duration), 181 IoStack::Disabled(v) => v.park_timeout(duration), 182 } 183 } 184 185 pub(crate) fn shutdown(&mut self, handle: &Handle) { 186 match self { 187 IoStack::Enabled(v) => v.shutdown(handle), 188 IoStack::Disabled(v) => v.shutdown(), 189 } 190 } 191 } 192 193 impl IoHandle { 194 pub(crate) fn unpark(&self) { 195 match self { 196 IoHandle::Enabled(handle) => handle.unpark(), 197 IoHandle::Disabled(handle) => handle.unpark(), 198 } 199 } 200 201 pub(crate) fn as_ref(&self) -> Option<&crate::runtime::io::Handle> { 202 match self { 203 IoHandle::Enabled(v) => Some(v), 204 IoHandle::Disabled(..) => None, 205 } 206 } 207 } 208 } 209 210 cfg_not_io_driver! { 211 pub(crate) type IoHandle = UnparkThread; 212 213 #[derive(Debug)] 214 pub(crate) struct IoStack(ParkThread); 215 216 fn create_io_stack(_enabled: bool, _nevents: usize) -> io::Result<(IoStack, IoHandle, SignalHandle)> { 217 let park_thread = ParkThread::new(); 218 let unpark_thread = park_thread.unpark(); 219 Ok((IoStack(park_thread), unpark_thread, Default::default())) 220 } 221 222 impl IoStack { 223 pub(crate) fn park(&mut self, _handle: &Handle) { 224 self.0.park(); 225 } 226 227 pub(crate) fn park_timeout(&mut self, _handle: &Handle, duration: Duration) { 228 self.0.park_timeout(duration); 229 } 230 231 pub(crate) fn shutdown(&mut self, _handle: &Handle) { 232 self.0.shutdown(); 233 } 234 235 /// This is not a "real" driver, so it is not considered enabled. 236 pub(crate) fn is_enabled(&self) -> bool { 237 false 238 } 239 } 240 } 241 242 // ===== signal driver ===== 243 244 cfg_signal_internal_and_unix! { 245 type SignalDriver = crate::runtime::signal::Driver; 246 pub(crate) type SignalHandle = Option<crate::runtime::signal::Handle>; 247 248 fn create_signal_driver(io_driver: IoDriver, io_handle: &crate::runtime::io::Handle) -> io::Result<(SignalDriver, SignalHandle)> { 249 let driver = crate::runtime::signal::Driver::new(io_driver, io_handle)?; 250 let handle = driver.handle(); 251 Ok((driver, Some(handle))) 252 } 253 } 254 255 cfg_not_signal_internal! { 256 pub(crate) type SignalHandle = (); 257 258 cfg_io_driver! { 259 type SignalDriver = IoDriver; 260 261 fn create_signal_driver(io_driver: IoDriver, _io_handle: &crate::runtime::io::Handle) -> io::Result<(SignalDriver, SignalHandle)> { 262 Ok((io_driver, ())) 263 } 264 } 265 } 266 267 // ===== process driver ===== 268 269 cfg_process_driver! { 270 type ProcessDriver = crate::runtime::process::Driver; 271 272 fn create_process_driver(signal_driver: SignalDriver) -> ProcessDriver { 273 ProcessDriver::new(signal_driver) 274 } 275 } 276 277 cfg_not_process_driver! { 278 cfg_io_driver! { 279 type ProcessDriver = SignalDriver; 280 281 fn create_process_driver(signal_driver: SignalDriver) -> ProcessDriver { 282 signal_driver 283 } 284 } 285 } 286 287 // ===== time driver ===== 288 289 cfg_time! { 290 #[derive(Debug)] 291 pub(crate) enum TimeDriver { 292 Enabled { 293 driver: crate::runtime::time::Driver, 294 }, 295 Disabled(IoStack), 296 } 297 298 pub(crate) type Clock = crate::time::Clock; 299 pub(crate) type TimeHandle = Option<crate::runtime::time::Handle>; 300 301 fn create_clock(enable_pausing: bool, start_paused: bool) -> Clock { 302 crate::time::Clock::new(enable_pausing, start_paused) 303 } 304 305 fn create_time_driver( 306 enable: bool, 307 io_stack: IoStack, 308 clock: &Clock, 309 ) -> (TimeDriver, TimeHandle) { 310 if enable { 311 let (driver, handle) = crate::runtime::time::Driver::new(io_stack, clock); 312 313 (TimeDriver::Enabled { driver }, Some(handle)) 314 } else { 315 (TimeDriver::Disabled(io_stack), None) 316 } 317 } 318 319 impl TimeDriver { 320 pub(crate) fn is_enabled(&self) -> bool { 321 match self { 322 TimeDriver::Enabled { .. } => true, 323 TimeDriver::Disabled(inner) => inner.is_enabled(), 324 } 325 } 326 327 pub(crate) fn park(&mut self, handle: &Handle) { 328 match self { 329 TimeDriver::Enabled { driver, .. } => driver.park(handle), 330 TimeDriver::Disabled(v) => v.park(handle), 331 } 332 } 333 334 pub(crate) fn park_timeout(&mut self, handle: &Handle, duration: Duration) { 335 match self { 336 TimeDriver::Enabled { driver } => driver.park_timeout(handle, duration), 337 TimeDriver::Disabled(v) => v.park_timeout(handle, duration), 338 } 339 } 340 341 pub(crate) fn shutdown(&mut self, handle: &Handle) { 342 match self { 343 TimeDriver::Enabled { driver } => driver.shutdown(handle), 344 TimeDriver::Disabled(v) => v.shutdown(handle), 345 } 346 } 347 } 348 } 349 350 cfg_not_time! { 351 type TimeDriver = IoStack; 352 353 pub(crate) type Clock = (); 354 pub(crate) type TimeHandle = (); 355 356 fn create_clock(_enable_pausing: bool, _start_paused: bool) -> Clock { 357 () 358 } 359 360 fn create_time_driver( 361 _enable: bool, 362 io_stack: IoStack, 363 _clock: &Clock, 364 ) -> (TimeDriver, TimeHandle) { 365 (io_stack, ()) 366 } 367 } 368