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();
    }
}