1 | use std::{ |
2 | cell::{Ref, RefCell, RefMut}, |
3 | ops::{BitOr, BitOrAssign}, |
4 | rc::Rc, |
5 | }; |
6 | |
7 | use log::trace; |
8 | |
9 | pub use crate::loop_logic::EventIterator; |
10 | use crate::{sys::TokenFactory, Poll, Readiness, RegistrationToken, Token}; |
11 | |
12 | pub mod channel; |
13 | #[cfg (feature = "executor" )] |
14 | #[cfg_attr (docsrs, doc(cfg(feature = "executor" )))] |
15 | pub mod futures; |
16 | pub mod generic; |
17 | pub mod ping; |
18 | #[cfg (all(target_os = "linux" , feature = "signals" ))] |
19 | #[cfg_attr (docsrs, doc(cfg(target_os = "linux" )))] |
20 | pub mod signals; |
21 | pub mod timer; |
22 | pub mod transient; |
23 | |
24 | /// Possible actions that can be requested to the event loop by an |
25 | /// event source once its events have been processed. |
26 | /// |
27 | /// `PostAction` values can be combined with the `|` (bit-or) operator (or with |
28 | /// `|=`) with the result that: |
29 | /// - if both values are identical, the result is that value |
30 | /// - if they are different, the result is [`Reregister`](PostAction::Reregister) |
31 | /// |
32 | /// Bit-or-ing these results is useful for composed sources to combine the |
33 | /// results of their child sources, but note that it only applies to the child |
34 | /// sources. For example, if every child source returns `Continue`, the result |
35 | /// will be `Continue`, but the parent source might still need to return |
36 | /// `Reregister` or something else depending on any additional logic it uses. |
37 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
38 | pub enum PostAction { |
39 | /// Continue listening for events on this source as before |
40 | Continue, |
41 | /// Trigger a re-registration of this source |
42 | Reregister, |
43 | /// Disable this source |
44 | /// |
45 | /// Has the same effect as [`LoopHandle::disable`](crate::LoopHandle#method.disable) |
46 | Disable, |
47 | /// Remove this source from the eventloop |
48 | /// |
49 | /// Has the same effect as [`LoopHandle::kill`](crate::LoopHandle#method.kill) |
50 | Remove, |
51 | } |
52 | |
53 | /// Combines `PostAction` values returned from nested event sources. |
54 | impl BitOr for PostAction { |
55 | type Output = Self; |
56 | |
57 | fn bitor(self, rhs: Self) -> Self::Output { |
58 | if matches!(self, x if x == rhs) { |
59 | self |
60 | } else { |
61 | Self::Reregister |
62 | } |
63 | } |
64 | } |
65 | |
66 | /// Combines `PostAction` values returned from nested event sources. |
67 | impl BitOrAssign for PostAction { |
68 | fn bitor_assign(&mut self, rhs: Self) { |
69 | if *self != rhs { |
70 | *self = Self::Reregister; |
71 | } |
72 | } |
73 | } |
74 | |
75 | /// Trait representing an event source |
76 | /// |
77 | /// This is the trait you need to implement if you wish to create your own |
78 | /// calloop-compatible event sources. |
79 | /// |
80 | /// The 3 associated types define the type of closure the user will need to |
81 | /// provide to process events for your event source. |
82 | /// |
83 | /// The `process_events` method will be called when one of the FD you registered |
84 | /// is ready, with the associated readiness and token. |
85 | /// |
86 | /// The `register`, `reregister` and `unregister` methods are plumbing to let your |
87 | /// source register itself with the polling system. See their documentation for details. |
88 | /// |
89 | /// In case your event source needs to do some special processing before or after a |
90 | /// polling session occurs (to prepare the underlying source for polling, and cleanup |
91 | /// after that), you can override [`NEEDS_EXTRA_LIFECYCLE_EVENTS`] to `true`. |
92 | /// For all sources for which that constant is `true`, the methods [`before_sleep`] and |
93 | /// [`before_handle_events`] will be called. |
94 | /// [`before_sleep`] is called before the polling system performs a poll operation. |
95 | /// [`before_handle_events`] is called before any process_events methods have been called. |
96 | /// This means that during `process_events` you can assume that all cleanup has occured on |
97 | /// all sources. |
98 | /// |
99 | /// [`NEEDS_EXTRA_LIFECYCLE_EVENTS`]: EventSource::NEEDS_EXTRA_LIFECYCLE_EVENTS |
100 | /// [`before_sleep`]: EventSource::before_sleep |
101 | /// [`before_handle_events`]: EventSource::before_handle_events |
102 | pub trait EventSource { |
103 | /// The type of events generated by your source. |
104 | type Event; |
105 | /// Some metadata of your event source |
106 | /// |
107 | /// This is typically useful if your source contains some internal state that |
108 | /// the user may need to interact with when processing events. The user callback |
109 | /// will receive a `&mut Metadata` reference. |
110 | /// |
111 | /// Set to `()` if not needed. |
112 | type Metadata; |
113 | /// The return type of the user callback |
114 | /// |
115 | /// If the user needs to return some value back to your event source once its |
116 | /// processing is finshed (to indicate success or failure for example), you can |
117 | /// specify it using this type. |
118 | /// |
119 | /// Set to `()` if not needed. |
120 | type Ret; |
121 | /// The error type returned from |
122 | /// [`process_events()`](Self::process_events()) (not the user callback!). |
123 | type Error: Into<Box<dyn std::error::Error + Sync + Send>>; |
124 | |
125 | /// Process any relevant events |
126 | /// |
127 | /// This method will be called every time one of the FD you registered becomes |
128 | /// ready, including the readiness details and the associated token. |
129 | /// |
130 | /// Your event source will then do some processing of the file descriptor(s) to generate |
131 | /// events, and call the provided `callback` for each one of them. |
132 | /// |
133 | /// You should ensure you drained the file descriptors of their events, especially if using |
134 | /// edge-triggered mode. |
135 | fn process_events<F>( |
136 | &mut self, |
137 | readiness: Readiness, |
138 | token: Token, |
139 | callback: F, |
140 | ) -> Result<PostAction, Self::Error> |
141 | where |
142 | F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret; |
143 | |
144 | /// Register yourself to this poll instance |
145 | /// |
146 | /// You should register all your relevant file descriptors to the provided [`Poll`](crate::Poll) |
147 | /// using its [`Poll::register`](crate::Poll#method.register) method. |
148 | /// |
149 | /// If you need to register more than one file descriptor, you can change the |
150 | /// `sub_id` field of the [`Token`](crate::Token) to differentiate between them. |
151 | fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()>; |
152 | |
153 | /// Re-register your file descriptors |
154 | /// |
155 | /// Your should update the registration of all your relevant file descriptor to |
156 | /// the provided [`Poll`](crate::Poll) using its [`Poll::reregister`](crate::Poll#method.reregister), |
157 | /// if necessary. |
158 | fn reregister( |
159 | &mut self, |
160 | poll: &mut Poll, |
161 | token_factory: &mut TokenFactory, |
162 | ) -> crate::Result<()>; |
163 | |
164 | /// Unregister your file descriptors |
165 | /// |
166 | /// You should unregister all your file descriptors from this [`Poll`](crate::Poll) using its |
167 | /// [`Poll::unregister`](crate::Poll#method.unregister) method. |
168 | fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()>; |
169 | |
170 | /// Whether this source needs to be sent the [`EventSource::before_sleep`] |
171 | /// and [`EventSource::before_handle_events`] notifications. These are opt-in because |
172 | /// they require more expensive checks, and almost all sources will not need these notifications |
173 | const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = false; |
174 | /// Notification that a single `poll` is about to begin |
175 | /// |
176 | /// Use this to perform operations which must be done before polling, |
177 | /// but which may conflict with other event handlers. For example, |
178 | /// if polling requires a lock to be taken |
179 | /// |
180 | /// If this returns Ok(Some), this will be treated as an event arriving in polling, and |
181 | /// your event handler will be called with the returned `Token` and `Readiness`. |
182 | /// Polling will however still occur, but with a timeout of 0, so additional events |
183 | /// from this or other sources may also be handled in the same iterations. |
184 | /// The returned `Token` must belong to this source |
185 | // If you need to return multiple synthetic events from this notification, please |
186 | // open an issue |
187 | fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> { |
188 | Ok(None) |
189 | } |
190 | /// Notification that polling is complete, and [`EventSource::process_events`] will |
191 | /// be called with the given events for this source. The iterator may be empty, |
192 | /// which indicates that no events were generated for this source |
193 | /// |
194 | /// Please note, the iterator excludes any synthetic events returned from |
195 | /// [`EventSource::before_sleep`] |
196 | /// |
197 | /// Use this to perform a cleanup before event handlers with arbitrary |
198 | /// code may run. This could be used to drop a lock obtained in |
199 | /// [`EventSource::before_sleep`] |
200 | #[allow (unused_variables)] |
201 | fn before_handle_events(&mut self, events: EventIterator<'_>) {} |
202 | } |
203 | |
204 | /// Blanket implementation for boxed event sources. [`EventSource`] is not an |
205 | /// object safe trait, so this does not include trait objects. |
206 | impl<T: EventSource> EventSource for Box<T> { |
207 | type Event = T::Event; |
208 | type Metadata = T::Metadata; |
209 | type Ret = T::Ret; |
210 | type Error = T::Error; |
211 | |
212 | fn process_events<F>( |
213 | &mut self, |
214 | readiness: Readiness, |
215 | token: Token, |
216 | callback: F, |
217 | ) -> Result<PostAction, Self::Error> |
218 | where |
219 | F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, |
220 | { |
221 | T::process_events(&mut **self, readiness, token, callback) |
222 | } |
223 | |
224 | fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> { |
225 | T::register(&mut **self, poll, token_factory) |
226 | } |
227 | |
228 | fn reregister( |
229 | &mut self, |
230 | poll: &mut Poll, |
231 | token_factory: &mut TokenFactory, |
232 | ) -> crate::Result<()> { |
233 | T::reregister(&mut **self, poll, token_factory) |
234 | } |
235 | |
236 | fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> { |
237 | T::unregister(&mut **self, poll) |
238 | } |
239 | |
240 | const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS; |
241 | |
242 | fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> { |
243 | T::before_sleep(&mut **self) |
244 | } |
245 | |
246 | fn before_handle_events(&mut self, events: EventIterator) { |
247 | T::before_handle_events(&mut **self, events) |
248 | } |
249 | } |
250 | |
251 | /// Blanket implementation for exclusive references to event sources. |
252 | /// [`EventSource`] is not an object safe trait, so this does not include trait |
253 | /// objects. |
254 | impl<T: EventSource> EventSource for &mut T { |
255 | type Event = T::Event; |
256 | type Metadata = T::Metadata; |
257 | type Ret = T::Ret; |
258 | type Error = T::Error; |
259 | |
260 | fn process_events<F>( |
261 | &mut self, |
262 | readiness: Readiness, |
263 | token: Token, |
264 | callback: F, |
265 | ) -> Result<PostAction, Self::Error> |
266 | where |
267 | F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, |
268 | { |
269 | T::process_events(&mut **self, readiness, token, callback) |
270 | } |
271 | |
272 | fn register(&mut self, poll: &mut Poll, token_factory: &mut TokenFactory) -> crate::Result<()> { |
273 | T::register(&mut **self, poll, token_factory) |
274 | } |
275 | |
276 | fn reregister( |
277 | &mut self, |
278 | poll: &mut Poll, |
279 | token_factory: &mut TokenFactory, |
280 | ) -> crate::Result<()> { |
281 | T::reregister(&mut **self, poll, token_factory) |
282 | } |
283 | |
284 | fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> { |
285 | T::unregister(&mut **self, poll) |
286 | } |
287 | |
288 | const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = T::NEEDS_EXTRA_LIFECYCLE_EVENTS; |
289 | |
290 | fn before_sleep(&mut self) -> crate::Result<Option<(Readiness, Token)>> { |
291 | T::before_sleep(&mut **self) |
292 | } |
293 | |
294 | fn before_handle_events(&mut self, events: EventIterator) { |
295 | T::before_handle_events(&mut **self, events) |
296 | } |
297 | } |
298 | |
299 | pub(crate) struct DispatcherInner<S, F> { |
300 | source: S, |
301 | callback: F, |
302 | needs_additional_lifecycle_events: bool, |
303 | } |
304 | |
305 | impl<Data, S, F> EventDispatcher<Data> for RefCell<DispatcherInner<S, F>> |
306 | where |
307 | S: EventSource, |
308 | F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret, |
309 | { |
310 | fn process_events( |
311 | &self, |
312 | readiness: Readiness, |
313 | token: Token, |
314 | data: &mut Data, |
315 | ) -> crate::Result<PostAction> { |
316 | let mut disp = self.borrow_mut(); |
317 | let DispatcherInner { |
318 | ref mut source, |
319 | ref mut callback, |
320 | .. |
321 | } = *disp; |
322 | trace!( |
323 | "[calloop] Processing events for source type {}" , |
324 | std::any::type_name::<S>() |
325 | ); |
326 | source |
327 | .process_events(readiness, token, |event, meta| callback(event, meta, data)) |
328 | .map_err(|e| crate::Error::OtherError(e.into())) |
329 | } |
330 | |
331 | fn register( |
332 | &self, |
333 | poll: &mut Poll, |
334 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
335 | token_factory: &mut TokenFactory, |
336 | ) -> crate::Result<()> { |
337 | let mut this = self.borrow_mut(); |
338 | |
339 | if this.needs_additional_lifecycle_events { |
340 | additional_lifecycle_register.register(token_factory.registration_token()); |
341 | } |
342 | this.source.register(poll, token_factory) |
343 | } |
344 | |
345 | fn reregister( |
346 | &self, |
347 | poll: &mut Poll, |
348 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
349 | token_factory: &mut TokenFactory, |
350 | ) -> crate::Result<bool> { |
351 | if let Ok(mut me) = self.try_borrow_mut() { |
352 | me.source.reregister(poll, token_factory)?; |
353 | if me.needs_additional_lifecycle_events { |
354 | additional_lifecycle_register.register(token_factory.registration_token()); |
355 | } |
356 | Ok(true) |
357 | } else { |
358 | Ok(false) |
359 | } |
360 | } |
361 | |
362 | fn unregister( |
363 | &self, |
364 | poll: &mut Poll, |
365 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
366 | registration_token: RegistrationToken, |
367 | ) -> crate::Result<bool> { |
368 | if let Ok(mut me) = self.try_borrow_mut() { |
369 | me.source.unregister(poll)?; |
370 | if me.needs_additional_lifecycle_events { |
371 | additional_lifecycle_register.unregister(registration_token); |
372 | } |
373 | Ok(true) |
374 | } else { |
375 | Ok(false) |
376 | } |
377 | } |
378 | |
379 | fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>> { |
380 | let mut disp = self.borrow_mut(); |
381 | let DispatcherInner { ref mut source, .. } = *disp; |
382 | source.before_sleep() |
383 | } |
384 | |
385 | fn before_handle_events(&self, events: EventIterator<'_>) { |
386 | let mut disp = self.borrow_mut(); |
387 | let DispatcherInner { ref mut source, .. } = *disp; |
388 | source.before_handle_events(events); |
389 | } |
390 | } |
391 | |
392 | pub(crate) trait EventDispatcher<Data> { |
393 | fn process_events( |
394 | &self, |
395 | readiness: Readiness, |
396 | token: Token, |
397 | data: &mut Data, |
398 | ) -> crate::Result<PostAction>; |
399 | |
400 | fn register( |
401 | &self, |
402 | poll: &mut Poll, |
403 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
404 | token_factory: &mut TokenFactory, |
405 | ) -> crate::Result<()>; |
406 | |
407 | fn reregister( |
408 | &self, |
409 | poll: &mut Poll, |
410 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
411 | token_factory: &mut TokenFactory, |
412 | ) -> crate::Result<bool>; |
413 | |
414 | fn unregister( |
415 | &self, |
416 | poll: &mut Poll, |
417 | additional_lifecycle_register: &mut AdditionalLifecycleEventsSet, |
418 | registration_token: RegistrationToken, |
419 | ) -> crate::Result<bool>; |
420 | |
421 | fn before_sleep(&self) -> crate::Result<Option<(Readiness, Token)>>; |
422 | fn before_handle_events(&self, events: EventIterator<'_>); |
423 | } |
424 | |
425 | #[derive (Default)] |
426 | /// The list of events |
427 | pub(crate) struct AdditionalLifecycleEventsSet { |
428 | /// The list of sources |
429 | pub(crate) values: Vec<RegistrationToken>, |
430 | } |
431 | |
432 | impl AdditionalLifecycleEventsSet { |
433 | fn register(&mut self, token: RegistrationToken) { |
434 | self.values.push(token) |
435 | } |
436 | |
437 | fn unregister(&mut self, token: RegistrationToken) { |
438 | self.values.retain(|it: &RegistrationToken| it != &token) |
439 | } |
440 | } |
441 | |
442 | // An internal trait to erase the `F` type parameter of `DispatcherInner` |
443 | trait ErasedDispatcher<'a, S, Data> { |
444 | fn as_source_ref(&self) -> Ref<S>; |
445 | fn as_source_mut(&self) -> RefMut<S>; |
446 | fn into_source_inner(self: Rc<Self>) -> S; |
447 | fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a>; |
448 | } |
449 | |
450 | impl<'a, S, Data, F> ErasedDispatcher<'a, S, Data> for RefCell<DispatcherInner<S, F>> |
451 | where |
452 | S: EventSource + 'a, |
453 | F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a, |
454 | { |
455 | fn as_source_ref(&self) -> Ref<S> { |
456 | Ref::map(self.borrow(), |inner: &DispatcherInner| &inner.source) |
457 | } |
458 | |
459 | fn as_source_mut(&self) -> RefMut<S> { |
460 | RefMut::map(self.borrow_mut(), |inner: &mut DispatcherInner| &mut inner.source) |
461 | } |
462 | |
463 | fn into_source_inner(self: Rc<Self>) -> S { |
464 | if let Ok(ref_cell: RefCell>) = Rc::try_unwrap(self) { |
465 | ref_cell.into_inner().source |
466 | } else { |
467 | panic!("Dispatcher is still registered" ); |
468 | } |
469 | } |
470 | |
471 | fn into_event_dispatcher(self: Rc<Self>) -> Rc<dyn EventDispatcher<Data> + 'a> |
472 | where |
473 | S: 'a, |
474 | { |
475 | self as Rc<dyn EventDispatcher<Data> + 'a> |
476 | } |
477 | } |
478 | |
479 | /// An event source with its callback. |
480 | /// |
481 | /// The `Dispatcher` can be registered in an event loop. |
482 | /// Use the `as_source_{ref,mut}` functions to interact with the event source. |
483 | /// Use `into_source_inner` to get the event source back. |
484 | pub struct Dispatcher<'a, S, Data>(Rc<dyn ErasedDispatcher<'a, S, Data> + 'a>); |
485 | |
486 | impl<'a, S, Data> std::fmt::Debug for Dispatcher<'a, S, Data> { |
487 | #[cfg_attr (feature = "nightly_coverage" , coverage(off))] |
488 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
489 | f.write_str(data:"Dispatcher { ... }" ) |
490 | } |
491 | } |
492 | |
493 | impl<'a, S, Data> Dispatcher<'a, S, Data> |
494 | where |
495 | S: EventSource + 'a, |
496 | { |
497 | /// Builds a dispatcher. |
498 | /// |
499 | /// The resulting `Dispatcher` |
500 | pub fn new<F>(source: S, callback: F) -> Self |
501 | where |
502 | F: FnMut(S::Event, &mut S::Metadata, &mut Data) -> S::Ret + 'a, |
503 | { |
504 | Dispatcher(Rc::new(RefCell::new(DispatcherInner { |
505 | source, |
506 | callback, |
507 | needs_additional_lifecycle_events: S::NEEDS_EXTRA_LIFECYCLE_EVENTS, |
508 | }))) |
509 | } |
510 | |
511 | /// Returns an immutable reference to the event source. |
512 | /// |
513 | /// # Panics |
514 | /// |
515 | /// Has the same semantics as `RefCell::borrow()`. |
516 | /// |
517 | /// The dispatcher being mutably borrowed while its events are dispatched, |
518 | /// this method will panic if invoked from within the associated dispatching closure. |
519 | pub fn as_source_ref(&self) -> Ref<S> { |
520 | self.0.as_source_ref() |
521 | } |
522 | |
523 | /// Returns a mutable reference to the event source. |
524 | /// |
525 | /// # Panics |
526 | /// |
527 | /// Has the same semantics as `RefCell::borrow_mut()`. |
528 | /// |
529 | /// The dispatcher being mutably borrowed while its events are dispatched, |
530 | /// this method will panic if invoked from within the associated dispatching closure. |
531 | pub fn as_source_mut(&self) -> RefMut<S> { |
532 | self.0.as_source_mut() |
533 | } |
534 | |
535 | /// Consumes the Dispatcher and returns the inner event source. |
536 | /// |
537 | /// # Panics |
538 | /// |
539 | /// Panics if the `Dispatcher` is still registered. |
540 | pub fn into_source_inner(self) -> S { |
541 | self.0.into_source_inner() |
542 | } |
543 | |
544 | pub(crate) fn clone_as_event_dispatcher(&self) -> Rc<dyn EventDispatcher<Data> + 'a> { |
545 | Rc::clone(&self.0).into_event_dispatcher() |
546 | } |
547 | } |
548 | |
549 | impl<'a, S, Data> Clone for Dispatcher<'a, S, Data> { |
550 | fn clone(&self) -> Dispatcher<'a, S, Data> { |
551 | Dispatcher(Rc::clone(&self.0)) |
552 | } |
553 | } |
554 | |
555 | /// An idle callback that was inserted in this loop |
556 | /// |
557 | /// This handle allows you to cancel the callback. Dropping |
558 | /// it will *not* cancel it. |
559 | pub struct Idle<'i> { |
560 | pub(crate) callback: Rc<RefCell<dyn CancellableIdle + 'i>>, |
561 | } |
562 | |
563 | impl<'i> std::fmt::Debug for Idle<'i> { |
564 | #[cfg_attr (feature = "nightly_coverage" , coverage(off))] |
565 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
566 | f.write_str(data:"Idle { ... }" ) |
567 | } |
568 | } |
569 | |
570 | impl<'i> Idle<'i> { |
571 | /// Cancel the idle callback if it was not already run |
572 | pub fn cancel(self) { |
573 | self.callback.borrow_mut().cancel(); |
574 | } |
575 | } |
576 | |
577 | pub(crate) trait CancellableIdle { |
578 | fn cancel(&mut self); |
579 | } |
580 | |
581 | impl<F> CancellableIdle for Option<F> { |
582 | fn cancel(&mut self) { |
583 | self.take(); |
584 | } |
585 | } |
586 | |
587 | pub(crate) trait IdleDispatcher<Data> { |
588 | fn dispatch(&mut self, data: &mut Data); |
589 | } |
590 | |
591 | impl<Data, F> IdleDispatcher<Data> for Option<F> |
592 | where |
593 | F: FnMut(&mut Data), |
594 | { |
595 | fn dispatch(&mut self, data: &mut Data) { |
596 | if let Some(callabck: &mut F) = self.as_mut() { |
597 | callabck(data); |
598 | } |
599 | } |
600 | } |
601 | |
602 | #[cfg (test)] |
603 | mod tests { |
604 | use std::time::Duration; |
605 | |
606 | use crate::{ping::make_ping, EventLoop}; |
607 | |
608 | // Test event source boxing. |
609 | #[test ] |
610 | fn test_boxed_source() { |
611 | let mut fired = false; |
612 | |
613 | let (pinger, source) = make_ping().unwrap(); |
614 | let boxed = Box::new(source); |
615 | |
616 | let mut event_loop = EventLoop::try_new().unwrap(); |
617 | let handle = event_loop.handle(); |
618 | |
619 | let token = handle |
620 | .insert_source(boxed, |_, _, fired| *fired = true) |
621 | .unwrap(); |
622 | |
623 | pinger.ping(); |
624 | |
625 | event_loop |
626 | .dispatch(Duration::new(0, 0), &mut fired) |
627 | .unwrap(); |
628 | |
629 | assert!(fired); |
630 | fired = false; |
631 | |
632 | handle.update(&token).unwrap(); |
633 | |
634 | pinger.ping(); |
635 | |
636 | event_loop |
637 | .dispatch(Duration::new(0, 0), &mut fired) |
638 | .unwrap(); |
639 | |
640 | assert!(fired); |
641 | fired = false; |
642 | |
643 | handle.remove(token); |
644 | |
645 | event_loop |
646 | .dispatch(Duration::new(0, 0), &mut fired) |
647 | .unwrap(); |
648 | |
649 | assert!(!fired); |
650 | } |
651 | |
652 | // Test event source trait methods via mut ref. |
653 | #[test ] |
654 | fn test_mut_ref_source() { |
655 | let mut fired = false; |
656 | |
657 | let (pinger, mut source) = make_ping().unwrap(); |
658 | let source_ref = &mut source; |
659 | |
660 | let mut event_loop = EventLoop::try_new().unwrap(); |
661 | let handle = event_loop.handle(); |
662 | |
663 | let token = handle |
664 | .insert_source(source_ref, |_, _, fired| *fired = true) |
665 | .unwrap(); |
666 | |
667 | pinger.ping(); |
668 | |
669 | event_loop |
670 | .dispatch(Duration::new(0, 0), &mut fired) |
671 | .unwrap(); |
672 | |
673 | assert!(fired); |
674 | fired = false; |
675 | |
676 | handle.update(&token).unwrap(); |
677 | |
678 | pinger.ping(); |
679 | |
680 | event_loop |
681 | .dispatch(Duration::new(0, 0), &mut fired) |
682 | .unwrap(); |
683 | |
684 | assert!(fired); |
685 | fired = false; |
686 | |
687 | handle.remove(token); |
688 | |
689 | event_loop |
690 | .dispatch(Duration::new(0, 0), &mut fired) |
691 | .unwrap(); |
692 | |
693 | assert!(!fired); |
694 | } |
695 | |
696 | // Test PostAction combinations. |
697 | #[test ] |
698 | fn post_action_combine() { |
699 | use super::PostAction::*; |
700 | assert_eq!(Continue | Continue, Continue); |
701 | assert_eq!(Continue | Reregister, Reregister); |
702 | assert_eq!(Continue | Disable, Reregister); |
703 | assert_eq!(Continue | Remove, Reregister); |
704 | |
705 | assert_eq!(Reregister | Continue, Reregister); |
706 | assert_eq!(Reregister | Reregister, Reregister); |
707 | assert_eq!(Reregister | Disable, Reregister); |
708 | assert_eq!(Reregister | Remove, Reregister); |
709 | |
710 | assert_eq!(Disable | Continue, Reregister); |
711 | assert_eq!(Disable | Reregister, Reregister); |
712 | assert_eq!(Disable | Disable, Disable); |
713 | assert_eq!(Disable | Remove, Reregister); |
714 | |
715 | assert_eq!(Remove | Continue, Reregister); |
716 | assert_eq!(Remove | Reregister, Reregister); |
717 | assert_eq!(Remove | Disable, Reregister); |
718 | assert_eq!(Remove | Remove, Remove); |
719 | } |
720 | |
721 | // Test PostAction self-assignment. |
722 | #[test ] |
723 | fn post_action_combine_assign() { |
724 | use super::PostAction::*; |
725 | |
726 | let mut action = Continue; |
727 | action |= Continue; |
728 | assert_eq!(action, Continue); |
729 | |
730 | let mut action = Continue; |
731 | action |= Reregister; |
732 | assert_eq!(action, Reregister); |
733 | |
734 | let mut action = Continue; |
735 | action |= Disable; |
736 | assert_eq!(action, Reregister); |
737 | |
738 | let mut action = Continue; |
739 | action |= Remove; |
740 | assert_eq!(action, Reregister); |
741 | |
742 | let mut action = Reregister; |
743 | action |= Continue; |
744 | assert_eq!(action, Reregister); |
745 | |
746 | let mut action = Reregister; |
747 | action |= Reregister; |
748 | assert_eq!(action, Reregister); |
749 | |
750 | let mut action = Reregister; |
751 | action |= Disable; |
752 | assert_eq!(action, Reregister); |
753 | |
754 | let mut action = Reregister; |
755 | action |= Remove; |
756 | assert_eq!(action, Reregister); |
757 | |
758 | let mut action = Disable; |
759 | action |= Continue; |
760 | assert_eq!(action, Reregister); |
761 | |
762 | let mut action = Disable; |
763 | action |= Reregister; |
764 | assert_eq!(action, Reregister); |
765 | |
766 | let mut action = Disable; |
767 | action |= Disable; |
768 | assert_eq!(action, Disable); |
769 | |
770 | let mut action = Disable; |
771 | action |= Remove; |
772 | assert_eq!(action, Reregister); |
773 | |
774 | let mut action = Remove; |
775 | action |= Continue; |
776 | assert_eq!(action, Reregister); |
777 | |
778 | let mut action = Remove; |
779 | action |= Reregister; |
780 | assert_eq!(action, Reregister); |
781 | |
782 | let mut action = Remove; |
783 | action |= Disable; |
784 | assert_eq!(action, Reregister); |
785 | |
786 | let mut action = Remove; |
787 | action |= Remove; |
788 | assert_eq!(action, Remove); |
789 | } |
790 | } |
791 | |