1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
use std::cell::RefCell; use std::io; use std::rc::Rc; use std::sync::Arc; use mio::{ event::{Event, Source as MioSource}, Interest, Registry, Token, Waker, }; use crate::list::ErasedList; pub mod channel; pub mod generic; #[cfg(target_os = "linux")] pub mod signals; pub mod timer; /// Trait representing a source that can be inserted into an EventLoop /// /// This is the interface between the source and the loop, you need to /// implement it to use your custom event sources. /// /// Two kind of event sources are possible, OS-based, or purely userspace. /// /// OS-based event sources rely on some ressource that is managed by the /// OS and for which it can signal readiness (a socket par example). /// /// Purely userspace event sources are not, and need to manually signal /// readiness to the event queue via a `Waker`. /// /// The distinction between the two kind is made depending on the return /// value of the implementation of the `as_mio_source` method. The /// default implementation returns `None`, meaning that the source is /// purely userspace. If your source is OS-based, you need to provide the /// necessary `mio` glue as a return value. /// /// See [`EventDispatcher`](trait.EventDispatcher.html) for details about /// how both kind of sources are dispatched. pub trait EventSource { /// The type of events generated by your sources type Event; /// Access the `mio`-aware resource for this source /// /// This type is what will be forwarded to the underlying `mio::Poll` /// for registration. /// /// If you are implementing the `EventSource` trait for a type /// that already implement `mio::event::Source`, the implementation /// of this method can be as simple as the following: /// /// ```ignore /// fn as_mio_source(&mut self) -> Option<&mut dyn MioSource> { /// Some(self) /// } /// ``` fn as_mio_source(&mut self) -> Option<&mut dyn MioSource> { None } /// The requested interest for OS-based sources /// /// This method is ignored for purely userspace event sources. fn interest(&self) -> Interest { Interest::READABLE } /// Build an `EventDispatcher` for this event source /// /// Your dispatcher is responsible for converting the basic /// readiness information into your `Event` type, and forwarding /// it to the callback. /// /// For example, a wrapper around a socket may read & parse a message /// and provide the parsed message to the callback. /// /// If your source is userspace and require some initialization, this is the /// place to do it. You are provided a waker that you'll need to use to /// signal the event loop for readiness. OS-based sources should ignore it. /// /// See [`EventDispatcher`](trait.EventDispatcher.html) for details about /// how dispatching occurs. fn make_dispatcher<Data: 'static, F: FnMut(Self::Event, &mut Data) + 'static>( &mut self, callback: F, waker: &Arc<Waker>, ) -> Rc<RefCell<dyn EventDispatcher<Data>>>; } /// An event dispatcher /// /// It is the junction between user callbacks and and an event source, /// receiving readinesses events, converting them into appropriate events /// and calling their inner user callback. /// /// Depending on the kind of your source, the dispatching will be done /// differently. /// /// - OS-based source will receive an `mio::Event` signalling the readiness /// of their resource. Note that there may be spurious wakeups and the /// resource may end up not being actually ready. When receiving a readiness /// event you should process the resource until it is no longer ready, or you /// might never receive any future notification (as the source would never /// "become" ready again). /// - Purely userspace sources are polled every time the event loop wakes up (be it /// from `mio` or a `waker`). As calloop cannot identify which of them is ready, /// all of them are called with a `None` value for readiness. Your source is then /// responsible for checking if it is actually ready, and if yes call its underlying /// callback appropriately. pub trait EventDispatcher<Data> { /// The source has a readiness event fn ready(&mut self, ready: Option<&Event>, data: &mut Data); } /// An event source that has been inserted into the event loop /// /// This handle allows you to remove it, and possibly more interactions /// depending on the source kind that will be provided by the `Deref` /// implementation of this struct to the evented object. /// /// Dropping this handle does not deregister this source from the event loop, /// but will drop the wrapped `EventSource`, maybe rendering it inert depending on /// its implementation. pub struct Source<E: EventSource> { pub(crate) source: E, pub(crate) registry: Rc<Registry>, pub(crate) list: Rc<RefCell<dyn ErasedList>>, pub(crate) token: Token, } impl<E: EventSource> Source<E> { /// Refresh the registration of this event source to the loop /// /// This can be necessary if the evented object provides methods to change /// its behavior. Its documentation should inform you of the need for re-registration. pub fn reregister(&mut self) -> io::Result<()> { let interest = self.source.interest(); if let Some(mio_source) = self.source.as_mio_source() { self.registry.reregister(mio_source, self.token, interest) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } } /// Remove this source from the event loop /// /// You are given the evented object back. pub fn remove(mut self) -> E { if let Some(mio_source) = self.source.as_mio_source() { let _ = self.registry.deregister(mio_source); } let _dispatcher = self.list.borrow_mut().del_source(self.token); self.source } } impl<E: EventSource> ::std::ops::Deref for Source<E> { type Target = E; fn deref(&self) -> &E { &self.source } } impl<E: EventSource> ::std::ops::DerefMut for Source<E> { fn deref_mut(&mut self) -> &mut E { &mut self.source } } /// An idle callback that was inserted in this loop /// /// This handle allows you to cancel the callback. Dropping /// it will *not* cancel it. pub struct Idle { pub(crate) callback: Rc<RefCell<dyn ErasedIdle>>, } impl Idle { /// Cancel the idle callback if it was not already run pub fn cancel(self) { self.callback.borrow_mut().cancel(); } } pub(crate) trait ErasedIdle { fn cancel(&mut self); } impl<Data> ErasedIdle for Option<Box<dyn FnMut(&mut Data)>> { fn cancel(&mut self) { self.take(); } }