1use std::borrow::Borrow;
2use std::collections::BTreeMap;
3use std::fmt;
4use std::future::Future;
5use std::io;
6use std::marker::PhantomData;
7use std::mem;
8use std::panic;
9use std::pin::Pin;
10use std::sync::atomic::{AtomicUsize, Ordering};
11use std::sync::{Arc, Mutex, MutexGuard, OnceLock};
12use std::task::{ready, Context, Poll, Waker};
13use std::time::{Duration, Instant};
14
15use concurrent_queue::ConcurrentQueue;
16use polling::{Event, Events, Poller};
17use slab::Slab;
18
19cfg_if::cfg_if! {
21 if #[cfg(any(
22 target_vendor = "apple",
23 target_os = "freebsd",
24 target_os = "netbsd",
25 target_os = "openbsd",
26 target_os = "dragonfly",
27 ))] {
28 mod kqueue;
29 pub use kqueue::Registration;
30 } else if #[cfg(unix)] {
31 mod unix;
32 pub use unix::Registration;
33 } else {
34 compile_error!("unsupported platform");
35 }
36}
37
38#[cfg(not(target_os = "espidf"))]
39const TIMER_QUEUE_SIZE: usize = 1000;
40
41#[cfg(target_os = "espidf")]
44const TIMER_QUEUE_SIZE: usize = 100;
45
46const READ: usize = 0;
47const WRITE: usize = 1;
48
49pub(crate) struct Reactor {
53 pub(crate) poller: Poller,
57
58 ticker: AtomicUsize,
65
66 sources: Mutex<Slab<Arc<Source>>>,
68
69 events: Mutex<Events>,
73
74 timers: Mutex<BTreeMap<(Instant, usize), Waker>>,
80
81 timer_ops: ConcurrentQueue<TimerOp>,
86}
87
88impl Reactor {
89 pub(crate) fn get() -> &'static Reactor {
91 static REACTOR: OnceLock<Reactor> = OnceLock::new();
92
93 REACTOR.get_or_init(|| {
94 crate::driver::init();
95 Reactor {
96 poller: Poller::new().expect("cannot initialize I/O event notification"),
97 ticker: AtomicUsize::new(0),
98 sources: Mutex::new(Slab::new()),
99 events: Mutex::new(Events::new()),
100 timers: Mutex::new(BTreeMap::new()),
101 timer_ops: ConcurrentQueue::bounded(TIMER_QUEUE_SIZE),
102 }
103 })
104 }
105
106 pub(crate) fn ticker(&self) -> usize {
108 self.ticker.load(Ordering::SeqCst)
109 }
110
111 pub(crate) fn insert_io(&self, raw: Registration) -> io::Result<Arc<Source>> {
113 let source = {
115 let mut sources = self.sources.lock().unwrap();
116 let key = sources.vacant_entry().key();
117 let source = Arc::new(Source {
118 registration: raw,
119 key,
120 state: Default::default(),
121 });
122 sources.insert(source.clone());
123 source
124 };
125
126 if let Err(err) = source.registration.add(&self.poller, source.key) {
128 let mut sources = self.sources.lock().unwrap();
129 sources.remove(source.key);
130 return Err(err);
131 }
132
133 Ok(source)
134 }
135
136 pub(crate) fn remove_io(&self, source: &Source) -> io::Result<()> {
138 let mut sources = self.sources.lock().unwrap();
139 sources.remove(source.key);
140 source.registration.delete(&self.poller)
141 }
142
143 pub(crate) fn insert_timer(&self, when: Instant, waker: &Waker) -> usize {
147 static ID_GENERATOR: AtomicUsize = AtomicUsize::new(1);
149 let id = ID_GENERATOR.fetch_add(1, Ordering::Relaxed);
150
151 while self
153 .timer_ops
154 .push(TimerOp::Insert(when, id, waker.clone()))
155 .is_err()
156 {
157 let mut timers = self.timers.lock().unwrap();
159 self.process_timer_ops(&mut timers);
160 }
161
162 self.notify();
164
165 id
166 }
167
168 pub(crate) fn remove_timer(&self, when: Instant, id: usize) {
170 while self.timer_ops.push(TimerOp::Remove(when, id)).is_err() {
172 let mut timers = self.timers.lock().unwrap();
174 self.process_timer_ops(&mut timers);
175 }
176 }
177
178 pub(crate) fn notify(&self) {
180 self.poller.notify().expect("failed to notify reactor");
181 }
182
183 pub(crate) fn lock(&self) -> ReactorLock<'_> {
185 let reactor = self;
186 let events = self.events.lock().unwrap();
187 ReactorLock { reactor, events }
188 }
189
190 pub(crate) fn try_lock(&self) -> Option<ReactorLock<'_>> {
192 self.events.try_lock().ok().map(|events| {
193 let reactor = self;
194 ReactorLock { reactor, events }
195 })
196 }
197
198 fn process_timers(&self, wakers: &mut Vec<Waker>) -> Option<Duration> {
202 #[cfg(feature = "tracing")]
203 let span = tracing::trace_span!("process_timers");
204 #[cfg(feature = "tracing")]
205 let _enter = span.enter();
206
207 let mut timers = self.timers.lock().unwrap();
208 self.process_timer_ops(&mut timers);
209
210 let now = Instant::now();
211
212 let pending = timers.split_off(&(now + Duration::from_nanos(1), 0));
217 let ready = mem::replace(&mut *timers, pending);
218
219 let dur = if ready.is_empty() {
221 timers
223 .keys()
224 .next()
225 .map(|(when, _)| when.saturating_duration_since(now))
226 } else {
227 Some(Duration::from_secs(0))
229 };
230
231 drop(timers);
233
234 #[cfg(feature = "tracing")]
236 tracing::trace!("{} ready wakers", ready.len());
237
238 for (_, waker) in ready {
239 wakers.push(waker);
240 }
241
242 dur
243 }
244
245 fn process_timer_ops(&self, timers: &mut MutexGuard<'_, BTreeMap<(Instant, usize), Waker>>) {
247 self.timer_ops
250 .try_iter()
251 .take(self.timer_ops.capacity().unwrap())
252 .for_each(|op| match op {
253 TimerOp::Insert(when, id, waker) => {
254 timers.insert((when, id), waker);
255 }
256 TimerOp::Remove(when, id) => {
257 timers.remove(&(when, id));
258 }
259 });
260 }
261}
262
263pub(crate) struct ReactorLock<'a> {
265 reactor: &'a Reactor,
266 events: MutexGuard<'a, Events>,
267}
268
269impl ReactorLock<'_> {
270 pub(crate) fn react(&mut self, timeout: Option<Duration>) -> io::Result<()> {
272 #[cfg(feature = "tracing")]
273 let span = tracing::trace_span!("react");
274 #[cfg(feature = "tracing")]
275 let _enter = span.enter();
276
277 let mut wakers = Vec::new();
278
279 let next_timer = self.reactor.process_timers(&mut wakers);
281
282 let timeout = match (next_timer, timeout) {
284 (None, None) => None,
285 (Some(t), None) | (None, Some(t)) => Some(t),
286 (Some(a), Some(b)) => Some(a.min(b)),
287 };
288
289 let tick = self
291 .reactor
292 .ticker
293 .fetch_add(1, Ordering::SeqCst)
294 .wrapping_add(1);
295
296 self.events.clear();
297
298 let res = match self.reactor.poller.wait(&mut self.events, timeout) {
300 Ok(0) => {
302 if timeout != Some(Duration::from_secs(0)) {
303 self.reactor.process_timers(&mut wakers);
305 }
306 Ok(())
307 }
308
309 Ok(_) => {
311 let sources = self.reactor.sources.lock().unwrap();
313
314 for ev in self.events.iter() {
315 if let Some(source) = sources.get(ev.key) {
317 let mut state = source.state.lock().unwrap();
318
319 for &(dir, emitted) in &[(WRITE, ev.writable), (READ, ev.readable)] {
321 if emitted {
322 state[dir].tick = tick;
323 state[dir].drain_into(&mut wakers);
324 }
325 }
326
327 if !state[READ].is_empty() || !state[WRITE].is_empty() {
331 let event = {
333 let mut event = Event::none(source.key);
334 event.readable = !state[READ].is_empty();
335 event.writable = !state[WRITE].is_empty();
336 event
337 };
338
339 source.registration.modify(&self.reactor.poller, event)?;
341 }
342 }
343 }
344
345 Ok(())
346 }
347
348 Err(err) if err.kind() == io::ErrorKind::Interrupted => Ok(()),
350
351 Err(err) => Err(err),
353 };
354
355 #[cfg(feature = "tracing")]
357 tracing::trace!("{} ready wakers", wakers.len());
358 for waker in wakers {
359 panic::catch_unwind(|| waker.wake()).ok();
361 }
362
363 res
364 }
365}
366
367enum TimerOp {
369 Insert(Instant, usize, Waker),
370 Remove(Instant, usize),
371}
372
373#[derive(Debug)]
375pub(crate) struct Source {
376 registration: Registration,
378
379 key: usize,
381
382 state: Mutex<[Direction; 2]>,
384}
385
386#[derive(Debug, Default)]
388struct Direction {
389 tick: usize,
391
392 ticks: Option<(usize, usize)>,
394
395 waker: Option<Waker>,
397
398 wakers: Slab<Option<Waker>>,
402}
403
404impl Direction {
405 fn is_empty(&self) -> bool {
407 self.waker.is_none() && self.wakers.iter().all(|(_, opt)| opt.is_none())
408 }
409
410 fn drain_into(&mut self, dst: &mut Vec<Waker>) {
412 if let Some(w) = self.waker.take() {
413 dst.push(w);
414 }
415 for (_, opt) in self.wakers.iter_mut() {
416 if let Some(w) = opt.take() {
417 dst.push(w);
418 }
419 }
420 }
421}
422
423impl Source {
424 pub(crate) fn poll_readable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
426 self.poll_ready(READ, cx)
427 }
428
429 pub(crate) fn poll_writable(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
431 self.poll_ready(WRITE, cx)
432 }
433
434 fn poll_ready(&self, dir: usize, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
438 let mut displaced = None;
439 let result = {
440 let mut state = self.state.lock().unwrap();
441
442 if let Some((a, b)) = state[dir].ticks {
444 if state[dir].tick != a && state[dir].tick != b {
445 state[dir].ticks = None;
446 return Poll::Ready(Ok(()));
447 }
448 }
449
450 let was_empty = state[dir].is_empty();
451
452 if let Some(w) = state[dir].waker.take() {
454 if w.will_wake(cx.waker()) {
455 state[dir].waker = Some(w);
456 return Poll::Pending;
457 }
458 displaced = Some(w);
459 }
460 state[dir].waker = Some(cx.waker().clone());
461 state[dir].ticks = Some((state[dir].tick, state[dir].tick));
462
463 if was_empty {
465 let event = {
467 let mut event = Event::none(self.key);
468 event.readable = !state[READ].is_empty();
469 event.writable = !state[WRITE].is_empty();
470 event
471 };
472
473 if let Err(err) = self.registration.modify(&Reactor::get().poller, event) {
475 Poll::Ready(Err(err))
476 } else {
477 Poll::Pending
478 }
479 } else {
480 Poll::Pending
481 }
482 };
483
484 if let Some(w) = displaced {
485 panic::catch_unwind(|| w.wake()).ok();
486 }
487 result
488 }
489
490 pub(crate) fn readable<T>(handle: &crate::Async<T>) -> Readable<'_, T> {
492 Readable(Self::ready(handle, READ))
493 }
494
495 pub(crate) fn readable_owned<T>(handle: Arc<crate::Async<T>>) -> ReadableOwned<T> {
497 ReadableOwned(Self::ready(handle, READ))
498 }
499
500 pub(crate) fn writable<T>(handle: &crate::Async<T>) -> Writable<'_, T> {
502 Writable(Self::ready(handle, WRITE))
503 }
504
505 pub(crate) fn writable_owned<T>(handle: Arc<crate::Async<T>>) -> WritableOwned<T> {
507 WritableOwned(Self::ready(handle, WRITE))
508 }
509
510 fn ready<H: Borrow<crate::Async<T>> + Clone, T>(handle: H, dir: usize) -> Ready<H, T> {
512 Ready {
513 handle,
514 dir,
515 ticks: None,
516 index: None,
517 _capture: PhantomData,
518 }
519 }
520}
521
522#[must_use = "futures do nothing unless you `.await` or poll them"]
524pub struct Readable<'a, T>(Ready<&'a crate::Async<T>, T>);
525
526impl<T> Future for Readable<'_, T> {
527 type Output = io::Result<()>;
528
529 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
530 ready!(Pin::new(&mut self.0).poll(cx))?;
531 #[cfg(feature = "tracing")]
532 tracing::trace!(fd = ?self.0.handle.source.registration, "readable");
533 Poll::Ready(Ok(()))
534 }
535}
536
537impl<T> fmt::Debug for Readable<'_, T> {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 f.debug_struct("Readable").finish()
540 }
541}
542
543#[must_use = "futures do nothing unless you `.await` or poll them"]
545pub struct ReadableOwned<T>(Ready<Arc<crate::Async<T>>, T>);
546
547impl<T> Future for ReadableOwned<T> {
548 type Output = io::Result<()>;
549
550 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
551 ready!(Pin::new(&mut self.0).poll(cx))?;
552 #[cfg(feature = "tracing")]
553 tracing::trace!(fd = ?self.0.handle.source.registration, "readable_owned");
554 Poll::Ready(Ok(()))
555 }
556}
557
558impl<T> fmt::Debug for ReadableOwned<T> {
559 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
560 f.debug_struct("ReadableOwned").finish()
561 }
562}
563
564#[must_use = "futures do nothing unless you `.await` or poll them"]
566pub struct Writable<'a, T>(Ready<&'a crate::Async<T>, T>);
567
568impl<T> Future for Writable<'_, T> {
569 type Output = io::Result<()>;
570
571 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
572 ready!(Pin::new(&mut self.0).poll(cx))?;
573 #[cfg(feature = "tracing")]
574 tracing::trace!(fd = ?self.0.handle.source.registration, "writable");
575 Poll::Ready(Ok(()))
576 }
577}
578
579impl<T> fmt::Debug for Writable<'_, T> {
580 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581 f.debug_struct("Writable").finish()
582 }
583}
584
585#[must_use = "futures do nothing unless you `.await` or poll them"]
587pub struct WritableOwned<T>(Ready<Arc<crate::Async<T>>, T>);
588
589impl<T> Future for WritableOwned<T> {
590 type Output = io::Result<()>;
591
592 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
593 ready!(Pin::new(&mut self.0).poll(cx))?;
594 #[cfg(feature = "tracing")]
595 tracing::trace!(fd = ?self.0.handle.source.registration, "writable_owned");
596 Poll::Ready(Ok(()))
597 }
598}
599
600impl<T> fmt::Debug for WritableOwned<T> {
601 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
602 f.debug_struct("WritableOwned").finish()
603 }
604}
605
606struct Ready<H: Borrow<crate::Async<T>>, T> {
607 handle: H,
608 dir: usize,
609 ticks: Option<(usize, usize)>,
610 index: Option<usize>,
611 _capture: PhantomData<fn() -> T>,
612}
613
614impl<H: Borrow<crate::Async<T>>, T> Unpin for Ready<H, T> {}
615
616impl<H: Borrow<crate::Async<T>> + Clone, T> Future for Ready<H, T> {
617 type Output = io::Result<()>;
618
619 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
620 let Self {
621 ref handle,
622 dir,
623 ticks,
624 index,
625 ..
626 } = &mut *self;
627
628 let mut state = handle.borrow().source.state.lock().unwrap();
629
630 if let Some((a, b)) = *ticks {
632 if state[*dir].tick != a && state[*dir].tick != b {
633 return Poll::Ready(Ok(()));
634 }
635 }
636
637 let was_empty = state[*dir].is_empty();
638
639 let i = match *index {
641 Some(i) => i,
642 None => {
643 let i = state[*dir].wakers.insert(None);
644 *index = Some(i);
645 *ticks = Some((state[*dir].tick, state[*dir].tick));
646 i
647 }
648 };
649 state[*dir].wakers[i] = Some(cx.waker().clone());
650
651 if was_empty {
653 let event = {
655 let mut event = Event::none(handle.borrow().source.key);
656 event.readable = !state[READ].is_empty();
657 event.writable = !state[WRITE].is_empty();
658 event
659 };
660
661 handle
663 .borrow()
664 .source
665 .registration
666 .modify(&Reactor::get().poller, event)?;
667 }
668
669 Poll::Pending
670 }
671}
672
673impl<H: Borrow<crate::Async<T>>, T> Drop for Ready<H, T> {
674 fn drop(&mut self) {
675 if let Some(key) = self.index {
677 let mut state = self.handle.borrow().source.state.lock().unwrap();
678 let wakers = &mut state[self.dir].wakers;
679 if wakers.contains(key) {
680 wakers.remove(key);
681 }
682 }
683 }
684}