| 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 | |