### Initialize writable test Source: https://docs.rs/calloop/0.14.4/src/calloop/io.rs.html Setup boilerplate for testing writable stream states. ```rust #[test] fn writable() { use std::io::{BufReader, BufWriter, Read, Write}; let mut event_loop = crate::EventLoop::try_new().unwrap(); let handle = event_loop.handle(); let (exec, sched) = executor().unwrap(); handle .insert_source(exec, move |(), &mut (), got| { *got = true; }) .unwrap(); let (mut tx, mut rx) = std::os::unix::net::UnixStream::pair().unwrap(); ``` -------------------------------- ### Usage of batch_reregister Source: https://docs.rs/calloop/0.14.4/calloop/macro.batch_reregister.html Example showing how to invoke the macro with a poll instance, token factory, and multiple event sources. ```rust calloop::batch_reregister!( poll, token_factory, self.source_one, self.source_two, self.source_three, self.source_four, ) ``` -------------------------------- ### Batch Macro Test Implementation Source: https://docs.rs/calloop/0.14.4/src/calloop/macros.rs.html Example implementation of EventSource using batch_register within a test module. ```rust fn register( &mut self, poll: &mut crate::Poll, token_factory: &mut crate::TokenFactory, ) -> crate::Result<()> { crate::batch_register!(poll, token_factory, self.ping0, self.ping1, self.ping2) } ``` -------------------------------- ### enable Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Enables a previously disabled event source to start generating events again. ```APIDOC ## enable ### Description Enables this previously disabled event source. This previously disabled source will start generating events again. Note: this cannot be done from within the source callback. ### Parameters - **token** (RegistrationToken) - Required - The token associated with the event source. ### Response - **Result** (Result<(), crate::Error>) - Returns Ok(()) on success or an error if the token is invalid. ``` -------------------------------- ### Basic Event Loop with Timer Source: https://docs.rs/calloop/0.14.4/calloop/index.html This example shows how to set up an event loop that waits for a timer to expire. It demonstrates inserting a timer event source and using a LoopSignal to stop the loop from within the callback. The event loop is configured to wait for a maximum of 20ms between events. ```Rust use calloop::{timer::{Timer, TimeoutAction}, EventLoop, LoopSignal}; fn main() { // Create the event loop. The loop is parameterised by the kind of shared // data you want the callbacks to use. In this case, we want to be able to // stop the loop when the timer fires, so we provide the loop with a // LoopSignal, which has the ability to stop the loop from within events. We // just annotate the type here; the actual data is provided later in the // run() call. let mut event_loop: EventLoop = EventLoop::try_new().expect("Failed to initialize the event loop!"); // Retrieve a handle. It is used to insert new sources into the event loop // It can be cloned, allowing you to insert sources from within source // callbacks. let handle = event_loop.handle(); // Create our event source, a timer, that will expire in 2 seconds let source = Timer::from_duration(std::time::Duration::from_secs(2)); // Inserting an event source takes this general form. It can also be done // from within the callback of another event source. handle .insert_source( // a type which implements the EventSource trait source, // a callback that is invoked whenever this source generates an event |event, _metadata, shared_data| { // This callback is given 3 values: // - the event generated by the source (in our case, timer events are the Instant // representing the deadline for which it has fired) // - &mut access to some metadata, specific to the event source (in our case, a // timer handle) // - &mut access to the global shared data that was passed to EventLoop::run or // EventLoop::dispatch (in our case, a LoopSignal object to stop the loop) // // The return type is just () because nothing uses it. Some // sources will expect a Result of some kind instead. println!("Timeout for {:?} expired!", event); // notify the event loop to stop running using the signal in the shared data // (see below) shared_data.stop(); // The timer event source requires us to return a TimeoutAction to // specify if the timer should be rescheduled. In our case we just drop it. TimeoutAction::Drop }, ) .expect("Failed to insert event source!"); // Create the shared data for our loop. let mut shared_data = event_loop.get_signal(); // Actually run the event loop. This will dispatch received events to their // callbacks, waiting at most 20ms for new events between each invocation of // the provided callback (pass None for the timeout argument if you want to // wait indefinitely between events). // // This is where we pass the *value* of the shared data, as a mutable // reference that will be forwarded to all your callbacks, allowing them to // share some state event_loop .run( std::time::Duration::from_millis(20), &mut shared_data, |_shared_data| { // Finally, this is where you can insert the processing you need // to do do between each waiting event eg. drawing logic if // you're doing a GUI app. }, ) .expect("Error during event loop!"); } ``` -------------------------------- ### TimerWheel Initialization Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/timer.rs.html Creates a new, empty TimerWheel. The wheel is initialized with an empty binary heap and a counter starting at 0. ```rust pub(crate) fn new() -> TimerWheel { TimerWheel { heap: BinaryHeap::new(), counter: 0, } } ``` -------------------------------- ### Change Socket Interests (Read/Write) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html This example shows how to change the interests of a registered source. It demonstrates registering a socket for reading, writing to it, and then changing its interest to writing and observing the dispatch behavior. ```rust use rustix::io::write; use rustix::net::{recv, socketpair, AddressFamily, RecvFlags, SocketFlags, SocketType}; let mut event_loop = EventLoop::::try_new().unwrap(); let (sock1, sock2) = socketpair( AddressFamily::UNIX, SocketType::STREAM, SocketFlags::empty(), None, // recv with DONTWAIT will suffice for platforms without SockFlag::SOCK_NONBLOCKING such as macOS ) .unwrap(); let source = Generic::new(sock1, Interest::READ, Mode::Level); let dispatcher = Dispatcher::new(source, |_, fd, dispatched| { *dispatched = true; // read all contents available to drain the socket let mut buf = [0u8; 32]; loop { match recv(&*fd, &mut buf, RecvFlags::DONTWAIT) { Ok((0, _)) => break, // closed pipe, we are now inert Ok(_) => {} Err(e) => { let e: std::io::Error = e.into(); if e.kind() == std::io::ErrorKind::WouldBlock { break; // nothing more to read } else { // propagate error return Err(e); } } } } Ok(PostAction::Continue) }); let sock_token_1 = event_loop .handle() .register_dispatcher(dispatcher.clone()) .unwrap(); // first dispatch, nothing is readable let mut dispatched = false; event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert!(!dispatched); // write something, the socket becomes readable write(&sock2, &[1, 2, 3]).unwrap(); dispatched = false; event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert!(dispatched); // All has been read, no longer readable dispatched = false; event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert!(!dispatched); // change the interests for writability instead dispatcher.as_source_mut().interest = Interest::WRITE; event_loop.handle().update(&sock_token_1).unwrap(); // the socket is writable dispatched = false; event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert!(dispatched); // change back to readable dispatcher.as_source_mut().interest = Interest::READ; event_loop.handle().update(&sock_token_1).unwrap(); // the socket is not readable dispatched = false; event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert!(!dispatched); ``` -------------------------------- ### Executor and Scheduler Initialization Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/futures.rs.html Initializes a new Executor and Scheduler pair. This function may fail if OS limits prevent the setup of internal pipes. ```APIDOC ## fn executor() -> crate::Result<(Executor, Scheduler) ### Description Initializes a new Executor and Scheduler pair. This function may fail due to OS errors preventing calloop from setting up its internal pipes, for example, if the process has reached its file descriptor limit. ### Returns A tuple containing the `Executor` and `Scheduler` instances. ### Errors Returns `crate::Result` which can contain `ExecutorError` if OS errors occur during pipe setup. ``` -------------------------------- ### Example: Using Weak Loop Handle in Timer Callback Source: https://docs.rs/calloop/0.14.4/calloop/struct.LoopHandle.html Demonstrates how to use a weak handle within an event loop's callback to avoid reference cycles. The weak handle is upgraded to an owned handle for use. ```rust use calloop::timer::{TimeoutAction, Timer}; use calloop::EventLoop; let event_loop: EventLoop<()> = EventLoop::try_new().unwrap(); let weak_handle = event_loop.handle().downgrade(); event_loop .handle() .insert_source(Timer::immediate(), move |_, _, _| { // Hold its weak handle in the event loop's callback to break the reference cycle. let handle = weak_handle.upgrade().unwrap(); // Use the upgraded handle later... TimeoutAction::Drop }) .unwrap(); ``` -------------------------------- ### Use batch_register Macro Source: https://docs.rs/calloop/0.14.4/calloop/macro.batch_register.html Example usage of the batch_register macro to register multiple event sources. This macro provides no scope for customization and uses try-or-early-return error handling. ```rust calloop::batch_register!( poll, token_factory, self.source_one, self.source_two, self.source_three, self.source_four, ) ``` -------------------------------- ### Usage of batch_unregister Source: https://docs.rs/calloop/0.14.4/calloop/macro.batch_unregister.html Example showing how to pass a poll instance and multiple event sources to the macro. Note that error handling occurs in the order of the provided sources. ```rust calloop::batch_unregister!( poll, self.source_one, self.source_two, self.source_three, self.source_four, ) ``` -------------------------------- ### Safely Get Err Value (Never Panics) in Rust Source: https://docs.rs/calloop/0.14.4/calloop/error/type.Result.html Use `into_err()` to get the contained `Err` value. This method is guaranteed not to panic, making it a compile-time safeguard against potential errors. ```rust fn only_bad_news() -> Result { Err("Oops, it failed".into()) } let error: String = only_bad_news().into_err(); println!("{error}"); ``` -------------------------------- ### Initialize and Run a Calloop Event Loop Source: https://docs.rs/calloop/0.14.4/src/calloop/lib.rs.html Demonstrates creating an event loop, registering a timer source with a callback, and running the loop with shared data. ```rust use calloop::{timer::{Timer, TimeoutAction}, EventLoop, LoopSignal}; fn main() { // Create the event loop. The loop is parameterised by the kind of shared // data you want the callbacks to use. In this case, we want to be able to // stop the loop when the timer fires, so we provide the loop with a // LoopSignal, which has the ability to stop the loop from within events. We // just annotate the type here; the actual data is provided later in the // run() call. let mut event_loop: EventLoop = EventLoop::try_new().expect("Failed to initialize the event loop!"); // Retrieve a handle. It is used to insert new sources into the event loop // It can be cloned, allowing you to insert sources from within source // callbacks. let handle = event_loop.handle(); // Create our event source, a timer, that will expire in 2 seconds let source = Timer::from_duration(std::time::Duration::from_secs(2)); // Inserting an event source takes this general form. It can also be done // from within the callback of another event source. handle .insert_source( // a type which implements the EventSource trait source, // a callback that is invoked whenever this source generates an event |event, _metadata, shared_data| { // This callback is given 3 values: // - the event generated by the source (in our case, timer events are the Instant // representing the deadline for which it has fired) // - &mut access to some metadata, specific to the event source (in our case, a // timer handle) // - &mut access to the global shared data that was passed to EventLoop::run or // EventLoop::dispatch (in our case, a LoopSignal object to stop the loop) // // The return type is just () because nothing uses it. Some // sources will expect a Result of some kind instead. println!("Timeout for {:?} expired!", event); // notify the event loop to stop running using the signal in the shared data // (see below) shared_data.stop(); // The timer event source requires us to return a TimeoutAction to // specify if the timer should be rescheduled. In our case we just drop it. TimeoutAction::Drop }, ) .expect("Failed to insert event source!"); // Create the shared data for our loop. let mut shared_data = event_loop.get_signal(); // Actually run the event loop. This will dispatch received events to their // callbacks, waiting at most 20ms for new events between each invocation of // the provided callback (pass None for the timeout argument if you want to // wait indefinitely between events). // // This is where we pass the *value* of the shared data, as a mutable // reference that will be forwarded to all your callbacks, allowing them to // share some state event_loop .run( std::time::Duration::from_millis(20), &mut shared_data, |_shared_data| { // Finally, this is where you can insert the processing you need // to do do between each waiting event eg. drawing logic if // you're doing a GUI app. ``` -------------------------------- ### Safely Get Ok Value (Never Panics) in Rust Source: https://docs.rs/calloop/0.14.4/calloop/error/type.Result.html Use `into_ok()` to get the contained `Ok` value. This method is guaranteed not to panic, making it a compile-time safeguard against potential errors. ```rust fn only_good_news() -> Result { Ok("this is fine".into()) } let s: String = only_good_news().into_ok(); println!("{s}"); ``` -------------------------------- ### Initialize SourceList Source: https://docs.rs/calloop/0.14.4/src/calloop/list.rs.html Provides a constructor for creating a new, empty SourceList. ```rust pub(crate) fn new() -> Self { SourceList { sources: Vec::new(), } } ``` -------------------------------- ### EventLoop::as_handle (Windows) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Gets the underlying handle of the poller on Windows systems. ```APIDOC ## EventLoop::as_handle ### Description Returns the underlying handle of the poller on Windows systems. ### Method `as_handle` ### Return Value `BorrowedHandle<'_>` - The borrowed handle. ``` -------------------------------- ### Initialize and run a timer-based event loop Source: https://docs.rs/calloop/0.14.4/calloop Demonstrates creating an EventLoop, inserting a timer source with a callback, and running the loop with shared data. ```rust use calloop::{timer::{Timer, TimeoutAction}, EventLoop, LoopSignal}; fn main() { // Create the event loop. The loop is parameterised by the kind of shared // data you want the callbacks to use. In this case, we want to be able to // stop the loop when the timer fires, so we provide the loop with a // LoopSignal, which has the ability to stop the loop from within events. We // just annotate the type here; the actual data is provided later in the // run() call. let mut event_loop: EventLoop = EventLoop::try_new().expect("Failed to initialize the event loop!"); // Retrieve a handle. It is used to insert new sources into the event loop // It can be cloned, allowing you to insert sources from within source // callbacks. let handle = event_loop.handle(); // Create our event source, a timer, that will expire in 2 seconds let source = Timer::from_duration(std::time::Duration::from_secs(2)); // Inserting an event source takes this general form. It can also be done // from within the callback of another event source. handle .insert_source( // a type which implements the EventSource trait source, // a callback that is invoked whenever this source generates an event |event, _metadata, shared_data| { // This callback is given 3 values: // - the event generated by the source (in our case, timer events are the Instant // representing the deadline for which it has fired) // - &mut access to some metadata, specific to the event source (in our case, a // timer handle) // - &mut access to the global shared data that was passed to EventLoop::run or // EventLoop::dispatch (in our case, a LoopSignal object to stop the loop) // // The return type is just () because nothing uses it. Some // sources will expect a Result of some kind instead. println!("Timeout for {:?} expired!", event); // notify the event loop to stop running using the signal in the shared data // (see below) shared_data.stop(); // The timer event source requires us to return a TimeoutAction to // specify if the timer should be rescheduled. In our case we just drop it. TimeoutAction::Drop }, ) .expect("Failed to insert event source!"); // Create the shared data for our loop. let mut shared_data = event_loop.get_signal(); // Actually run the event loop. This will dispatch received events to their // callbacks, waiting at most 20ms for new events between each invocation of // the provided callback (pass None for the timeout argument if you want to // wait indefinitely between events). // // This is where we pass the *value* of the shared data, as a mutable // reference that will be forwarded to all your callbacks, allowing them to // share some state event_loop .run( std::time::Duration::from_millis(20), &mut shared_data, |_shared_data| { // Finally, this is where you can insert the processing you need // to do do between each waiting event eg. drawing logic if // you're doing a GUI app. }, ) .expect("Error during event loop!"); } ``` -------------------------------- ### Get Handle (Windows) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Provides the underlying handle of the poller on Windows systems. ```rust impl AsHandle for EventLoop<'_, Data> { fn as_handle(&self) -> BorrowedHandle<'_> { self.poller.as_handle() } } ``` -------------------------------- ### Using Generic Event Source Source: https://docs.rs/calloop/0.14.4/calloop/generic/index.html Demonstrates how to wrap an IO object in a Generic event source to monitor for read readiness in level-triggering mode and handle readiness events within a callback. ```APIDOC ## POST /api/users ### Description Creates a new user in the system. ### Method POST ### Endpoint /api/users ### Parameters #### Query Parameters - **limit** (integer) - Optional - The maximum number of users to return. #### Request Body - **username** (string) - Required - The desired username for the new user. - **email** (string) - Required - The email address of the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com" } ``` ### Response #### Success Response (200) - **id** (integer) - The unique identifier for the newly created user. - **username** (string) - The username of the created user. - **email** (string) - The email address of the created user. #### Response Example ```json { "id": 123, "username": "johndoe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Create TransientSource using Into Source: https://docs.rs/calloop/0.14.4/calloop/transient/struct.TransientSource.html Demonstrates creating a TransientSource by converting an existing event source using the `Into` trait. This is the recommended way to initialize a TransientSource. ```rust let (sender, source) = channel(); let mpsc_receiver: TransientSource = source.into(); ``` -------------------------------- ### CloneToUninit (Nightly Only) Source: https://docs.rs/calloop/0.14.4/calloop/signals/enum.Signal.html This is a nightly-only experimental API that performs copy-assignment from `self` to a raw pointer destination. ```APIDOC #### unsafe fn clone_to_uninit(&self, dest: *mut u8) ### Description Performs copy-assignment from `self` to `dest`. ### Method `clone_to_uninit` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response None #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Implementations for Readiness Source: https://docs.rs/calloop/0.14.4/calloop/struct.Readiness.html Details the various trait implementations for the Readiness struct, such as Clone, Debug, Copy, and others. ```APIDOC ### impl Clone for Readiness #### fn clone(&self) -> Readiness Returns a duplicate of the value. #### fn clone_from(&mut self, source: &Self) Performs copy-assignment from `source`. ### impl Debug for Readiness #### fn fmt(&self, f: &mut Formatter<'_>) -> Result Formats the value using the given formatter. ### impl Copy for Readiness ### Auto Trait Implementations - Freeze - RefUnwindSafe - Send - Sync - Unpin - UnwindSafe ### Blanket Implementations - impl Any for T - impl Borrow for T - impl BorrowMut for T - impl CloneToUninit for T - impl From for T - impl Instrument for T - impl Into for T - impl ToOwned for T - impl TryFrom for T - impl TryInto for T - impl WithSubscriber for T ``` -------------------------------- ### EventLoop::as_raw_handle (Windows) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Gets the underlying raw handle of the poller on Windows systems. ```APIDOC ## EventLoop::as_raw_handle ### Description Returns the underlying raw handle of the poller on Windows systems. ### Method `as_raw_handle` ### Return Value `RawHandle` - The raw handle. ``` -------------------------------- ### Repeating Timer Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/timer.rs.html Shows how to set up a timer that repeats at a specified interval. Verifies that the timer callback is invoked multiple times. ```rust #[test] fn repeating_timer() { let mut event_loop = EventLoop::try_new().unwrap(); let mut dispatched = 0; event_loop .handle() .insert_source( Timer::from_duration(Duration::from_millis(500)), |_, &mut (), dispatched| { *dispatched += 1; TimeoutAction::ToDuration(Duration::from_millis(500)) }, ) .unwrap(); event_loop .dispatch(Some(Duration::from_millis(250)), &mut dispatched) .unwrap(); assert_eq!(dispatched, 0); event_loop .dispatch(Some(Duration::from_millis(510)), &mut dispatched) .unwrap(); assert_eq!(dispatched, 1); event_loop .dispatch(Some(Duration::from_millis(510)), &mut dispatched) .unwrap(); assert_eq!(dispatched, 2); event_loop .dispatch(Some(Duration::from_millis(510)), &mut dispatched) .unwrap(); assert_eq!(dispatched, 3); } ``` -------------------------------- ### EventLoop::as_fd (Unix) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Gets the underlying file descriptor of the poller on Unix-like systems. ```APIDOC ## EventLoop::as_fd ### Description Returns the underlying file descriptor of the poller. This can be used to create a `Generic` source from the current loop and insert it into another `EventLoop`. ### Method `as_fd` ### Return Value `BorrowedFd<'_>` - The borrowed file descriptor. ``` -------------------------------- ### Insert and Dispatch Multiple Sources Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Demonstrates inserting two ping sources into the event loop and dispatching events. Each ping triggers a dispatch, and the accumulated value is asserted. ```rust fn unregister(&mut self, poll: &mut Poll) -> crate::Result<()> { self.ping1.unregister(poll)?; self.ping2.unregister(poll)?; Ok(()) } } let mut event_loop = EventLoop::::try_new().unwrap(); let (ping1, source1) = make_ping().unwrap(); let (ping2, source2) = make_ping().unwrap(); let source = DoubleSource { ping1: source1, ping2: source2, }; event_loop .handle() .insert_source(source, |i, _, d| { eprintln!("Dispatching {}", i); *d += i }) .unwrap(); let mut dispatched = 0; ping1.ping(); event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert_eq!(dispatched, 1); dispatched = 0; ping2.ping(); event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert_eq!(dispatched, 2); dispatched = 0; ping1.ping(); ping2.ping(); event_loop .dispatch(Duration::ZERO, &mut dispatched) .unwrap(); assert_eq!(dispatched, 3); ``` -------------------------------- ### EventLoop::as_raw_fd (Unix) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Gets the underlying raw file descriptor of the poller on Unix-like systems. ```APIDOC ## EventLoop::as_raw_fd ### Description Returns the underlying raw file descriptor of the poller. This can be used to create a `Generic` source from the current loop and insert it into another `EventLoop`. It is recommended to clone the `fd` before doing so. ### Method `as_raw_fd` ### Return Value `RawFd` - The raw file descriptor. ``` -------------------------------- ### Get Raw Handle (Windows) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Provides the underlying raw handle of the poller on Windows systems. ```rust impl AsRawHandle for EventLoop<'_, Data> { fn as_raw_handle(&self) -> RawHandle { self.poller.as_raw_handle() } } ``` -------------------------------- ### Register and Dispatch Events with Calloop Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/transient.rs.html Demonstrates registering a dispatcher, sending pings to trigger events, and dispatching events through the event loop. Verifies the event ID increments correctly after each dispatch. ```rust // The top level source. let top = WrapperSource(outer); // Create a dispatcher so we can check the source afterwards. let dispatcher = Dispatcher::new(top, |got_id, _, test_id| { *test_id = got_id; }); let mut event_loop = crate::EventLoop::try_new().unwrap(); let handle = event_loop.handle(); let token = handle.register_dispatcher(dispatcher.clone()).unwrap(); // First loop run: the ping generates an event for the inner source. // The ID should be 1 after the increment in register(). pinger.ping(); event_loop.dispatch(Duration::ZERO, &mut id).unwrap(); assert_eq!(id, 1); // Second loop run: the ID should be 2 after the previous // process_events(). pinger.ping(); event_loop.dispatch(Duration::ZERO, &mut id).unwrap(); assert_eq!(id, 2); // Third loop run: the ID should be 3 after another process_events(). pinger.ping(); event_loop.dispatch(Duration::ZERO, &mut id).unwrap(); assert_eq!(id, 3); // Fourth loop run: the callback is no longer called by the inner // source, so our local ID is not incremented. pinger.ping(); event_loop.dispatch(Duration::ZERO, &mut id).unwrap(); assert_eq!(id, 3); // Remove the dispatcher so we can inspect the sources. handle.remove(token); let mut top_after = dispatcher.into_source_inner(); // I expect the inner source to be dropped, so the TransientSource // variant is None (its version of None, not Option::None), so its map() // won't call the passed-in function (hence the unreachable!()) and its // return value should be Option::None. assert!(top_after.0.map(|_| unreachable!()).is_none()); ``` -------------------------------- ### Create a Ping Event Source Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/ping.rs.html Initializes a new ping event source, returning a Ping handle and a PingSource. ```rust pub fn make_ping() -> std::io::Result<(Ping, PingSource)> { platform::make_ping() } ``` -------------------------------- ### TokenInner Get ID Method Source: https://docs.rs/calloop/0.14.4/src/calloop/token.rs.html Retrieves the ID from a `TokenInner` instance, converting it back to a usize. ```rust pub(crate) fn get_id(self) -> usize { self.id as usize } ``` -------------------------------- ### Batch Registration Macros Source: https://docs.rs/calloop/0.14.4/calloop Utility macros for performing bulk operations on multiple event sources simultaneously. ```APIDOC ## Macros ### batch_register Registers a set of event sources by calling `EventSource::register()` for each provided source. ### batch_reregister Reregisters a set of event sources by calling `EventSource::reregister()` for each provided source. ### batch_unregister Unregisters a set of event sources by calling `EventSource::unregister()` for each provided source. ``` -------------------------------- ### Get Type ID Source: https://docs.rs/calloop/0.14.4/calloop/channel/struct.Sender.html Retrieves the TypeId of the Sender. This is a blanket implementation for any type T that is 'static and ?Sized. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Get Event Loop Signal Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Retrieves a signal object used to stop the running event loop. ```rust pub fn get_signal(&self) -> LoopSignal { LoopSignal { ``` -------------------------------- ### Dispatcher Struct and Constructor Source: https://docs.rs/calloop/0.14.4/calloop/struct.Dispatcher.html Information about the Dispatcher struct and how to create a new instance. ```APIDOC ## Dispatcher ### Description An event source with its callback. The `Dispatcher` can be registered in an event loop. Use the `as_source_{ref,mut}` functions to interact with the event source. Use `into_source_inner` to get the event source back. ### Struct Definition ```rust pub struct Dispatcher<'a, S, Data>(/* private fields */); ``` ### Constructor #### `new` Builds a dispatcher. ##### Parameters - **source** (S) - The event source. - **callback** (F) - The callback function to be executed when an event occurs. ##### Returns A new `Dispatcher` instance. ##### Example ```rust let dispatcher = Dispatcher::new(source, |event, metadata, data| { // Handle event // ... }); ``` ``` -------------------------------- ### Module io Overview Source: https://docs.rs/calloop/0.14.4/calloop/io/index.html Overview of the io module, its purpose, and how to use its features. ```APIDOC ## Module io calloop # Module io Copy item path Source Search Settings Help ### Summary Expand description Adapters for async IO objects This module mainly hosts the `Async` adapter for making IO objects async with readiness monitoring backed by an `EventLoop`. See `LoopHandle::adapt_io` for how to create them. ## Structs ### Async Adapter for async IO manipulations ### Readable A future that resolves once the associated object becomes ready for reading ### Writable A future that resolves once the associated object becomes ready for writing ``` -------------------------------- ### Any Trait Implementation Source: https://docs.rs/calloop/0.14.4/calloop/io/struct.Writable.html Implements the Any trait for any type T, providing a way to get the TypeId of an object. This is a blanket implementation. ```rust impl Any for T where T: 'static + ?Sized, ``` -------------------------------- ### Define a leaked file descriptor structure Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Example of wrapping an OwnedFd in a ManuallyDrop structure for testing purposes. ```rust #[cfg(unix)] #[test] fn insert_bad_source() { use std::mem::ManuallyDrop; use std::os::unix::io::{AsFd, FromRawFd, OwnedFd}; struct LeakedFd(ManuallyDrop); impl AsFd for LeakedFd { ``` -------------------------------- ### Timer Struct and Constructors Source: https://docs.rs/calloop/0.14.4/calloop/timer/struct.Timer.html Information about the Timer struct and how to create new Timer instances. ```APIDOC ## Struct Timer ### Description A timer event source. When registered to the event loop, it will trigger an event once its deadline is reached. If the deadline is in the past relative to the moment of its insertion in the event loop, the `Timer` will trigger an event as soon as the event loop is dispatched. ### Constructors #### `immediate()` ```rust pub fn immediate() -> Timer ``` Create a timer that will fire immediately when inserted in the event loop. #### `from_duration(duration: Duration)` ```rust pub fn from_duration(duration: Duration) -> Timer ``` Create a timer that will fire after a given duration from now. #### `from_deadline(deadline: Instant)` ```rust pub fn from_deadline(deadline: Instant) -> Timer ``` Create a timer that will fire at a given instant. ``` -------------------------------- ### Get File Descriptor (Unix) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Provides the underlying file descriptor of the poller. Useful for creating `Generic` sources. ```rust impl AsFd for EventLoop<'_, Data> { /// Get the underlying fd of the poller. /// /// This could be used to create [`Generic`] source out of the current loop /// and inserting into some other [`EventLoop`]. /// /// [`Generic`]: crate::generic::Generic fn as_fd(&self) -> BorrowedFd<'_> { self.poller.as_fd() } } ``` -------------------------------- ### Handle Duplicate Source Insertion on Linux Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/generic.rs.html Demonstrates attempting to insert the same Unix stream source twice into the Calloop event loop on Linux. The second insertion should fail, but the original token remains valid. ```rust use std::os::unix::{ io::{AsFd, BorrowedFd}, net::UnixStream, }; let event_loop = crate::EventLoop::<()>::try_new().unwrap(); let handle = event_loop.handle(); let (_, rx) = UnixStream::pair().unwrap(); // Rc only implements AsFd since 1.69... struct RcFd { rc: std::rc::Rc, } impl AsFd for RcFd { fn as_fd(&self) -> BorrowedFd<'_> { self.rc.as_fd() } } let rx = std::rc::Rc::new(rx); let token = handle .insert_source( Generic::new(RcFd { rc: rx.clone() }, Interest::READ, Mode::Level), |_, _, _| Ok(PostAction::Continue), ) .unwrap(); // inserting the same FD a second time should fail let ret = handle.insert_source( Generic::new(RcFd { rc: rx.clone() }, Interest::READ, Mode::Level), |_, _, _| Ok(PostAction::Continue), ); assert!(ret.is_err()); std::mem::drop(ret); // but the original token is still registered handle.update(&token).unwrap(); ``` -------------------------------- ### Get Poller Reference Source: https://docs.rs/calloop/0.14.4/src/calloop/sys.rs.html Returns a reference to the underlying `Poller` instance. This is typically used for internal library operations. ```rust pub(crate) fn poller(&self) -> &Arc ``` -------------------------------- ### Create a timer from a deadline instant Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/timer.rs.html Create a timer that will trigger at a specific `Instant` in the future. This allows for precise scheduling. ```rust pub fn from_deadline(deadline: Instant) -> Timer { Self::from_deadline_inner(Some(deadline)) } ``` -------------------------------- ### Unwrap Error Value in Rust Source: https://docs.rs/calloop/0.14.4/calloop/error/type.Result.html Use `unwrap_err()` to get the contained `Err` value. Panics if the `Result` is an `Ok`. ```rust let x: Result = Ok(2); x.unwrap_err(); // panics with `2` ``` ```rust let x: Result = Err("emergency failure"); assert_eq!(x.unwrap_err(), "emergency failure"); ``` -------------------------------- ### Test basic sync_channel functionality Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/channel.rs.html Demonstrates using a bounded synchronous channel with the event loop, including filling the buffer and verifying closure behavior. ```rust #[test] fn basic_sync_channel() { let mut event_loop = crate::EventLoop::try_new().unwrap(); let handle = event_loop.handle(); let (tx, rx) = sync_channel::<()>(2); let mut received = (0, false); let _channel_token = handle .insert_source( rx, move |evt, &mut (), received: &mut (u32, bool)| match evt { Event::Msg(()) => { received.0 += 1; } Event::Closed => { received.1 = true; } }, ) .unwrap(); // nothing is sent, nothing is received event_loop .dispatch(Some(::std::time::Duration::ZERO), &mut received) .unwrap(); assert_eq!(received.0, 0); assert!(!received.1); // fill the channel tx.send(()).unwrap(); tx.send(()).unwrap(); assert!(tx.try_send(()).is_err()); // empty it event_loop .dispatch(Some(::std::time::Duration::ZERO), &mut received) .unwrap(); assert_eq!(received.0, 2); assert!(!received.1); // send a final message and drop the sender tx.send(()).unwrap(); std::mem::drop(tx); // final read of the channel event_loop .dispatch(Some(::std::time::Duration::ZERO), &mut received) .unwrap(); assert_eq!(received.0, 3); assert!(received.1); } ``` -------------------------------- ### Test Default EventSource Handlers Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Example of testing an EventSource implementation that relies on default lifecycle handler behavior. ```rust #[test] fn default_additional_events() { let (sender, channel) = channel(); let mut test_source = NoopWithDefaultHandlers { channel }; let mut event_loop = EventLoop::try_new().unwrap(); event_loop .handle() .insert_source(Box::new(&mut test_source), |_, _, _| {}) .unwrap(); sender.send(()).unwrap(); event_loop.dispatch(None, &mut ()).unwrap(); struct NoopWithDefaultHandlers { channel: Channel<()>, } impl EventSource for NoopWithDefaultHandlers { type Event = as EventSource>::Event; ``` -------------------------------- ### Unwrap Ok Value in Rust Source: https://docs.rs/calloop/0.14.4/calloop/error/type.Result.html Use `unwrap()` to get the contained value of an `Ok` variant. Panics if the `Result` is an `Err`. ```rust let x: Result = Ok(2); assert_eq!(x.unwrap(), 2); ``` -------------------------------- ### CloneToUninit Implementation (Nightly) Source: https://docs.rs/calloop/0.14.4/calloop/enum.PostAction.html An experimental nightly-only API that performs copy-assignment from a source to an uninitialized destination. Use with caution. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Test event loop with synthetic source Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Demonstrates testing an event loop using a custom source that implements before_sleep and before_handle_events hooks. ```rust #[test] fn additional_events_synthetic() { let mut event_loop: EventLoop<'_, Lock> = EventLoop::try_new().unwrap(); let mut lock = Lock { lock: Rc::new(Cell::new(false)), }; event_loop .handle() .insert_source( InstantWakeupLockingSource { lock: lock.clone(), token: None, }, |_, _, lock| { lock.lock(); lock.unlock(); }, ) .unwrap(); // Loop should finish, as event_loop.dispatch(None, &mut lock).unwrap(); #[derive(Clone)] struct Lock { lock: Rc>, } impl Lock { fn lock(&self) { if self.lock.get() { panic!(); } self.lock.set(true) } fn unlock(&self) { if !self.lock.get() { panic!(); } self.lock.set(false); } } struct InstantWakeupLockingSource { lock: Lock, token: Option, } impl EventSource for InstantWakeupLockingSource { type Event = (); type Metadata = (); type Ret = (); type Error = as EventSource>::Error; fn process_events( &mut self, _: Readiness, token: Token, mut callback: F, ) -> Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { assert_eq!(token, self.token.unwrap()); callback((), &mut ()); Ok(PostAction::Continue) } fn register( &mut self, _: &mut Poll, token_factory: &mut TokenFactory, ) -> crate::Result<()> { self.token = Some(token_factory.token()); Ok(()) } fn reregister(&mut self, _: &mut Poll, _: &mut TokenFactory) -> crate::Result<()> { unreachable!() } fn unregister(&mut self, _: &mut Poll) -> crate::Result<()> { unreachable!() } const NEEDS_EXTRA_LIFECYCLE_EVENTS: bool = true; fn before_sleep(&mut self) -> crate::Result> { self.lock.lock(); Ok(Some((Readiness::EMPTY, self.token.unwrap()))) } fn before_handle_events(&mut self, _: EventIterator) { self.lock.unlock(); } } } ``` -------------------------------- ### Manage Event Loop Sources Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Demonstrates inserting a ping source into the event loop and removing it upon execution. ```rust let handle = event_loop.handle(); let (ping, ping_source) = make_ping().unwrap(); let ping_token = event_loop .handle() .insert_source(ping_source, move |(), &mut (), opt_src| { if let Some(src) = opt_src.take() { handle.remove(src); } }) .unwrap(); ping.ping(); let mut opt_src = Some(ping_token); event_loop.dispatch(Duration::ZERO, &mut opt_src).unwrap(); assert!(opt_src.is_none()); } ``` -------------------------------- ### Get Raw File Descriptor (Unix) Source: https://docs.rs/calloop/0.14.4/src/calloop/loop_logic.rs.html Provides the underlying raw file descriptor of the poller. Useful for creating `Generic` sources. ```rust impl AsRawFd for EventLoop<'_, Data> { /// Get the underlying raw_fd of the poller. /// /// This could be used to create [`Generic`] source out of the current loop /// and inserting into some other [`EventLoop`]. It's recommended to clone `fd` /// before doing so. /// /// [`Generic`]: crate::generic::Generic fn as_raw_fd(&self) -> RawFd { self.poller.as_raw_fd() } } ``` -------------------------------- ### Insert and Run Event Loop Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/transient.rs.html Demonstrates inserting a custom event source into the calloop event loop and running the loop until a stop signal is received. This is a common pattern for integrating custom event handling. ```Rust let mut event_loop: crate::EventLoop<(Option, crate::LoopSignal)> = crate::EventLoop::try_new().unwrap(); let handle = event_loop.handle(); let signal = event_loop.get_signal(); // This is how we communicate with the event sources. let mut context = (None, signal); let _token = handle .insert_source(outer, |data, _, (evt, sig)| { *evt = Some(data); sig.stop(); }) .unwrap(); // Ensure our sources fire. ping0_tx.ping(); ping1_tx.ping(); // Use run() rather than dispatch() because it's not strictly part of // any API contract as to how many runs of the event loop it takes to // replace the nested source. event_loop.run(None, &mut context, |_| {}).unwrap(); ``` -------------------------------- ### Getting the Next Deadline Source: https://docs.rs/calloop/0.14.4/src/calloop/sources/timer.rs.html Returns the deadline of the next timeout in the TimerWheel without removing it. This is useful for determining the earliest future event. ```rust pub(crate) fn next_deadline(&self) -> Option { self.heap.peek().map(|data| data.deadline) } ``` -------------------------------- ### Get Notifier for Poll Source: https://docs.rs/calloop/0.14.4/src/calloop/sys.rs.html Provides a thread-safe handle to wake up the `Poll` instance. This is useful for inter-thread communication or signaling the event loop. ```rust pub(crate) fn notifier(&self) -> Notifier ``` -------------------------------- ### Get Mutable Reference to Underlying IO Object Source: https://docs.rs/calloop/0.14.4/calloop/io/struct.Async.html Provides mutable access to the underlying IO object wrapped by the Async adapter. ```rust pub fn get_mut(&mut self) -> &mut F ```