#[cfg(target_os = "linux")]
mod eventfd;
#[cfg(target_os = "linux")]
use eventfd as platform;
#[cfg(windows)]
mod iocp;
#[cfg(windows)]
use iocp as platform;
#[cfg(not(any(target_os = "linux", windows)))]
mod pipe;
#[cfg(not(any(target_os = "linux", windows)))]
use pipe as platform;
use std::fmt;
pub fn make_ping() -> std::io::Result<(Ping, PingSource)> {
platform::make_ping()
}
pub type Ping = platform::Ping;
pub type PingSource = platform::PingSource;
#[derive(Debug)]
pub struct PingError(Box<dyn std::error::Error + Sync + Send>);
impl fmt::Display for PingError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl std::error::Error for PingError {
#[cfg_attr(feature = "nightly_coverage", coverage(off))]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&*self.0)
}
}
#[cfg(test)]
mod tests {
use crate::transient::TransientSource;
use std::time::Duration;
use super::*;
#[test]
fn ping() {
let mut event_loop = crate::EventLoop::<bool>::try_new().unwrap();
let (ping, source) = make_ping().unwrap();
event_loop
.handle()
.insert_source(source, |(), &mut (), dispatched| *dispatched = true)
.unwrap();
ping.ping();
let mut dispatched = false;
event_loop
.dispatch(std::time::Duration::ZERO, &mut dispatched)
.unwrap();
assert!(dispatched);
let mut dispatched = false;
event_loop
.dispatch(std::time::Duration::ZERO, &mut dispatched)
.unwrap();
assert!(!dispatched);
}
#[test]
fn ping_closed() {
let mut event_loop = crate::EventLoop::<bool>::try_new().unwrap();
let (_, source) = make_ping().unwrap();
event_loop
.handle()
.insert_source(source, |(), &mut (), dispatched| *dispatched = true)
.unwrap();
let mut dispatched = false;
event_loop
.dispatch(std::time::Duration::ZERO, &mut dispatched)
.unwrap();
assert!(!dispatched);
let now = std::time::Instant::now();
event_loop
.dispatch(std::time::Duration::from_millis(100), &mut dispatched)
.unwrap();
assert!(now.elapsed() >= std::time::Duration::from_millis(100));
}
#[test]
fn ping_removed() {
let mut dispatched = false;
let mut event_loop = crate::EventLoop::<bool>::try_new().unwrap();
let (sender, source) = make_ping().unwrap();
let wrapper = TransientSource::from(source);
assert!(!wrapper.is_none());
let dispatcher =
crate::Dispatcher::new(wrapper, |(), &mut (), dispatched| *dispatched = true);
let token = event_loop
.handle()
.register_dispatcher(dispatcher.clone())
.unwrap();
drop(sender);
event_loop
.dispatch(Duration::ZERO, &mut dispatched)
.unwrap();
assert!(!dispatched);
event_loop.handle().remove(token);
let wrapper = dispatcher.into_source_inner();
assert!(wrapper.is_none());
}
#[test]
fn ping_fired_and_removed() {
let mut dispatched = false;
let mut event_loop = crate::EventLoop::<bool>::try_new().unwrap();
let (sender, source) = make_ping().unwrap();
let wrapper = TransientSource::from(source);
assert!(!wrapper.is_none());
let dispatcher =
crate::Dispatcher::new(wrapper, |(), &mut (), dispatched| *dispatched = true);
let token = event_loop
.handle()
.register_dispatcher(dispatcher.clone())
.unwrap();
sender.ping();
drop(sender);
event_loop
.dispatch(Duration::ZERO, &mut dispatched)
.unwrap();
assert!(dispatched);
event_loop.handle().remove(token);
let wrapper = dispatcher.into_source_inner();
assert!(wrapper.is_none());
}
#[test]
fn ping_multiple_senders() {
let mut dispatched = false;
let mut event_loop = crate::EventLoop::<bool>::try_new().unwrap();
let (sender0, source) = make_ping().unwrap();
let wrapper = TransientSource::from(source);
let sender1 = sender0.clone();
let sender2 = sender1.clone();
assert!(!wrapper.is_none());
let dispatcher =
crate::Dispatcher::new(wrapper, |(), &mut (), dispatched| *dispatched = true);
let token = event_loop
.handle()
.register_dispatcher(dispatcher.clone())
.unwrap();
sender0.ping();
drop(sender0);
event_loop
.dispatch(Duration::ZERO, &mut dispatched)
.unwrap();
assert!(dispatched);
dispatched = false;
sender1.ping();
event_loop
.dispatch(Duration::ZERO, &mut dispatched)
.unwrap();
assert!(dispatched);
dispatched = false;
drop(sender1);
drop(sender2);
event_loop
.dispatch(Duration::ZERO, &mut dispatched)
.unwrap();
assert!(!dispatched);
event_loop.handle().remove(token);
let wrapper = dispatcher.into_source_inner();
assert!(wrapper.is_none());
}
}