### Calloop Timer Event Source Examples Source: https://context7.com/smithay/calloop/llms.txt Provides examples of using the `Timer` event source in Calloop. It demonstrates creating immediate, one-shot, and repeating timers. The callback functions show how to handle timer events, update shared data, and control timer behavior using `TimeoutAction`. ```rust use calloop::EventLoop; use calloop::timer::{Timer, TimeoutAction}; use std::time::{Duration, Instant}; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); // Create an immediate timer handle.insert_source(Timer::immediate(), |deadline, _metadata, count| { println!("Immediate timer fired at {:?}", deadline); *count += 1; TimeoutAction::Drop })?; // Create a one-shot timer (fires after 500ms) handle.insert_source( Timer::from_duration(Duration::from_millis(500)), |deadline, _metadata, count| { println!("One-shot timer fired at {:?}", deadline); *count += 1; TimeoutAction::Drop }, )?; // Create a repeating timer (fires every 200ms) handle.insert_source( Timer::from_duration(Duration::from_millis(200)), |_deadline, _metadata, count| { *count += 1; println!("Repeating timer, count: {}", count); if *count >= 5 { TimeoutAction::Drop } else { TimeoutAction::ToDuration(Duration::from_millis(200)) } }, )?; let mut count = 0u32; // Run until all timers are done while count < 7 { event_loop.dispatch(Some(Duration::from_millis(100)), &mut count)?; } Ok(()) } ``` -------------------------------- ### Complete Calloop program with timer in Rust Source: https://github.com/smithay/calloop/blob/master/doc/src/ch02-02-timers.md Presents a full example of a calloop program that includes setting up an event loop, creating a timer, adding it to the loop with a callback, and running the loop. The callback demonstrates rescheduling the timer using `TimeoutAction::ToDuration` to create a recurring event. ```rust use std::time::{Duration, Instant}; use calloop::{EventLoop, LoopHandle}; use calloop::timer::Timer; struct SharedData; fn main() -> Result<(), Box> { let mut event_loop = EventLoop::::new()?; let loop_handle = event_loop.handle(); // Create a timer that fires every 1 second let timer = Timer::from_duration(Duration::from_secs(1)); // Insert the timer into the event loop loop_handle.insert_source(timer, move |current_time: Instant, _data: &mut (), _shared_data: &mut SharedData| { println!("Timer fired at {:?}", current_time); // Reschedule the timer to fire again after 1 second calloop::timer::TimeoutAction::ToDuration(Duration::from_secs(1)) })?; // Run the event loop event_loop.run()?; Ok(()) } ``` -------------------------------- ### Create Calloop Event Loop Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to create a new `EventLoop` instance with a specified shared data type and retrieve a `LoopHandle` for inserting event sources. The example shows initializing the loop with `i32` as shared data and performing a single event dispatch. ```rust use calloop::EventLoop; fn main() -> Result<(), Box> { // Create an event loop with `i32` as shared data type let mut event_loop: EventLoop = EventLoop::try_new()?; // Get a handle for inserting sources let handle = event_loop.handle(); // Shared data passed to all callbacks let mut counter = 0; // Dispatch events with a timeout of 100ms event_loop.dispatch(std::time::Duration::from_millis(100), &mut counter)?; Ok(()) } ``` -------------------------------- ### Initialize and Run a Timer Event Loop in Rust Source: https://github.com/smithay/calloop/blob/master/README.md This example demonstrates how to create an EventLoop, register a timer event source with a callback, and run the loop until the timer expires. It utilizes LoopSignal to manage the loop lifecycle and demonstrates passing shared data to callbacks. ```rust use calloop::{timer::{Timer, TimeoutAction}, EventLoop, LoopSignal}; fn main() { let mut event_loop: EventLoop = EventLoop::try_new().expect("Failed to initialize the event loop!"); let handle = event_loop.handle(); let source = Timer::from_duration(std::time::Duration::from_secs(2)); handle.insert_source( source, |event, _metadata, shared_data| { println!("Timeout for {:?} expired!", event); shared_data.stop(); TimeoutAction::Drop }, ).expect("Failed to insert event source!"); let mut shared_data = event_loop.get_signal(); event_loop.run( std::time::Duration::from_millis(20), &mut shared_data, |_shared_data| {}, ).expect("Error during event loop!"); } ``` -------------------------------- ### Run Calloop Event Loop with Timer and Signal Source: https://context7.com/smithay/calloop/llms.txt Illustrates how to run the `EventLoop` continuously using `run()`. It includes setting up a timer that stops the loop after a specified duration using `LoopSignal`. The example also shows an inter-iteration callback that can be used for tasks between event dispatches. ```rust use calloop::{EventLoop, LoopSignal}; use calloop::timer::{Timer, TimeoutAction}; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); // Insert a timer that stops the loop after 2 seconds handle.insert_source( Timer::from_duration(Duration::from_secs(2)), |_event, _metadata, signal| { println!("Timer fired! Stopping loop..."); signal.stop(); TimeoutAction::Drop }, )?; // Get the signal for shared data let mut signal = event_loop.get_signal(); // Run the loop with 20ms polling timeout // The closure is called between each dispatch event_loop.run(Duration::from_millis(20), &mut signal, |_signal| { // Inter-iteration work (e.g., rendering for GUI apps) })?; println!("Event loop stopped"); Ok(()) } ``` -------------------------------- ### Implementing Custom EventSource Source: https://context7.com/smithay/calloop/llms.txt Shows how to implement the EventSource trait to create a custom source. This example wraps a Ping source to maintain a stateful count of events triggered. ```rust use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory}; use calloop::ping::{make_ping, Ping, PingSource, PingError}; use calloop::EventLoop; use std::time::Duration; struct CountingPing { ping: Ping, source: PingSource, count: u32, } impl CountingPing { fn new() -> std::io::Result<(Self, Ping)> { let (ping, source) = make_ping()?; let ping_handle = ping.clone(); Ok(( CountingPing { ping, source, count: 0, }, ping_handle, )) } } impl EventSource for CountingPing { type Event = u32; type Metadata = (); type Ret = (); type Error = PingError; fn process_events( &mut self, readiness: Readiness, token: Token, mut callback: F, ) -> Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { self.source.process_events(readiness, token, |(), _| { self.count += 1; callback(self.count, &mut ()); }) } fn register(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> calloop::Result<()> { self.source.register(poll, factory) } fn reregister(&mut self, poll: &mut Poll, factory: &mut TokenFactory) -> calloop::Result<()> { self.source.reregister(poll, factory) } fn unregister(&mut self, poll: &mut Poll) -> calloop::Result<()> { self.source.unregister(poll) } } fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (source, ping) = CountingPing::new()?; handle.insert_source(source, |count, _metadata, last_count| { println!("Ping count: {}", count); *last_count = count; })?; let mut last_count = 0u32; for _ in 0..3 { ping.ping(); event_loop.dispatch(Some(Duration::ZERO), &mut last_count)?; } println!("Final count: {}", last_count); Ok(()) } ``` -------------------------------- ### Implement recursive event processing Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-04-creating-our-source-part-3-processing-events-almost.md An example implementation of process_events that delegates event handling to internal sub-sources like a ping receiver, an MPSC channel, and a ZeroMQ socket. ```rust fn process_events( &mut self, readiness: calloop::Readiness, token: calloop::Token, mut callback: F, ) -> Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { self.wake_ping_receiver .process_events(readiness, token, |_, _| {}) .context("Failed after registration")?; self.mpsc_receiver .process_events(readiness, token, |evt, _| { if let calloop::channel::Event::Msg(msg) = evt { self.socket .send_multipart(msg, 0) .context("Failed to send message")?; } })?; self.socket .process_events(readiness, token, |_, _| { let events = self.socket.get_events().context("Failed to read ZeroMQ events")?; if events.contains(zmq::POLLOUT) {} if events.contains(zmq::POLLIN) { let messages = self.socket.recv_multipart(0); } }) } ``` -------------------------------- ### Define Async Task Block Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-01-run-async-code.md Example of defining an async block that returns a value to the executor upon completion. ```rust {{#rustdoc_include async_example.rs:decl_async}} ``` -------------------------------- ### EventLoop Initialization and Usage Source: https://github.com/smithay/calloop/blob/master/README.md Demonstrates how to initialize an EventLoop, insert a timer event source with a callback, and run the loop until a signal is received. ```APIDOC ## POST /event-loop/run ### Description Initializes and executes an event loop that processes registered event sources. Callbacks are triggered when events occur, allowing for shared state management via a loop signal. ### Method POST ### Endpoint /event-loop/run ### Parameters #### Request Body - **timeout** (Duration) - Required - The maximum time to wait for events between loop iterations. - **shared_data** (Object) - Required - Mutable state shared across all event callbacks. ### Request Example { "timeout": "20ms", "shared_data": "LoopSignal" } ### Response #### Success Response (200) - **status** (string) - Indicates the loop has finished execution. #### Response Example { "status": "success" } ``` -------------------------------- ### Creating an Event Loop Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to create a new EventLoop instance with a specified shared data type and how to obtain a handle for inserting event sources. ```APIDOC ## Creating an Event Loop ### Description The `EventLoop` is the core type that manages event sources and dispatches events. Create one with `try_new()`, then use `handle()` to get a `LoopHandle` for inserting sources. The loop is parameterized by a shared data type that callbacks can access. ### Method `EventLoop::try_new()` ### Endpoint N/A (Library Function) ### Parameters #### Type Parameters - **shared_data** (Type) - The type of data shared across callbacks. ### Request Example ```rust use calloop::EventLoop; fn main() -> Result<(), Box> { // Create an event loop with `i32` as shared data type let mut event_loop: EventLoop = EventLoop::try_new()?; // Get a handle for inserting sources let handle = event_loop.handle(); // Shared data passed to all callbacks let mut counter = 0; // Dispatch events with a timeout of 100ms event_loop.dispatch(std::time::Duration::from_millis(100), &mut counter)?; Ok(()) } ``` ### Response #### Success Response (200) N/A (Library Function) #### Response Example N/A ``` -------------------------------- ### Async IO Adapter Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to adapt IO objects for asynchronous use with `LoopHandle::adapt_io`. This feature requires the `executor` and `futures-io` features to be enabled. ```APIDOC ## Async IO Adapter Adapt IO objects for async use with `LoopHandle::adapt_io`. Requires the `executor` and `futures-io` features. ### Description This example shows how to integrate standard IO objects (like `UnixStream`) into an asynchronous event loop by adapting them for async operations. It demonstrates scheduling read and write operations as futures. ### Method N/A (Example code, not an API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Code Example ```rust #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use calloop::EventLoop; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use calloop::sources::futures::executor; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use futures::io::{AsyncReadExt, AsyncWriteExt}; use std::os::unix::net::UnixStream; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (exec, scheduler) = executor::<()>()?; handle.insert_source(exec, |(), _metadata, done| { *done = true; })?; // Create a socket pair let (tx, rx) = UnixStream::pair()?; // Adapt both ends for async use let mut tx = handle.adapt_io(tx)?; let mut rx = handle.adapt_io(rx)?; // Schedule reading future scheduler.schedule(async move { let mut buf = [0u8; 12]; rx.read_exact(&mut buf).await.unwrap(); println!("Received: {}", String::from_utf8_lossy(&buf)); })?; // Schedule writing future scheduler.schedule(async move { tx.write_all(b"Hello World!").await.unwrap(); tx.flush().await.unwrap(); })?; let mut done = false; while !done { event_loop.dispatch(None, &mut done)?; } Ok(()) } #[cfg(not(all(unix, feature = "executor", feature = "futures-io")))] fn main() { println!("Async IO example requires Unix and 'executor' + 'futures-io' features"); } ``` ``` -------------------------------- ### Running the Event Loop Source: https://context7.com/smithay/calloop/llms.txt Shows how to continuously run the event loop using `run()`, which processes events and executes an inter-iteration callback. It also demonstrates using `LoopSignal` to stop the loop. ```APIDOC ## Running the Event Loop ### Description Use `run()` for continuous event processing with an inter-iteration callback, or `dispatch()` for single-shot dispatching. The `LoopSignal` allows stopping the loop from callbacks or other threads. ### Method `EventLoop::run()` ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```rust use calloop::{EventLoop, LoopSignal}; use calloop::timer::{Timer, TimeoutAction}; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); // Insert a timer that stops the loop after 2 seconds handle.insert_source( Timer::from_duration(Duration::from_secs(2)), |_event, _metadata, signal| { println!("Timer fired! Stopping loop..."); signal.stop(); TimeoutAction::Drop }, )?; // Get the signal for shared data let mut signal = event_loop.get_signal(); // Run the loop with 20ms polling timeout // The closure is called between each dispatch event_loop.run(Duration::from_millis(20), &mut signal, |_signal| { // Inter-iteration work (e.g., rendering for GUI apps) })?; println!("Event loop stopped"); Ok(()) } ``` ### Response #### Success Response (200) N/A (Library Function) #### Response Example N/A ``` -------------------------------- ### Initialize Calloop Executor and Scheduler Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-02-async-io-types.md Before working with async IO, obtain both an executor and a scheduler using the `calloop::futures::executor()` function. The executor is then integrated into the Calloop event loop. ```rust let (executor, _handle) = calloop::futures::executor(); let mut loop_handle = calloop::Loop::new().expect("Failed to create new event loop"); loop_handle.set_executor(executor); let scheduler = loop_handle.get_scheduler(); ``` -------------------------------- ### Adapt IO Objects for Async Usage Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to adapt standard IO objects like UnixStream for use with async/await syntax. Requires the 'executor' and 'futures-io' features to be enabled. ```rust #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use calloop::EventLoop; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use calloop::sources::futures::executor; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] use futures::io::{AsyncReadExt, AsyncWriteExt}; use std::os::unix::net::UnixStream; #[cfg(all(unix, feature = "executor", feature = "futures-io"))] fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (exec, scheduler) = executor::<()>()?; handle.insert_source(exec, |(), _metadata, done| { *done = true; })?; let (tx, rx) = UnixStream::pair()?; let mut tx = handle.adapt_io(tx)?; let mut rx = handle.adapt_io(rx)?; scheduler.schedule(async move { let mut buf = [0u8; 12]; rx.read_exact(&mut buf).await.unwrap(); println!("Received: {}", String::from_utf8_lossy(&buf)); })?; scheduler.schedule(async move { tx.write_all(b"Hello World!").await.unwrap(); tx.flush().await.unwrap(); })?; let mut done = false; while !done { event_loop.dispatch(None, &mut done)?; } Ok(()) } ``` -------------------------------- ### Manage Event Sources Dynamically Source: https://context7.com/smithay/calloop/llms.txt Explains how to use RegistrationToken to enable, disable, and remove event sources at runtime. ```rust use calloop::EventLoop; use calloop::ping::make_ping; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (ping, ping_source) = make_ping()?; let token = handle.insert_source(ping_source, |(), _metadata, count| { *count += 1; println!("Ping! Count: {}", count); })?; let mut count = 0u32; ping.ping(); event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After first ping: {}", count); handle.disable(&token)?; ping.ping(); event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After disabled ping: {}", count); handle.enable(&token)?; event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After re-enabled: {}", count); handle.remove(token); Ok(()) } ``` -------------------------------- ### Run Calloop Event Loop Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-02-async-io-types.md This snippet demonstrates how to run the Calloop event loop. It spawns the asynchronous sending and receiving tasks onto the executor and then enters the main loop, which continues until interrupted. ```rust let send_handle = scheduler.spawn(async_send(async_writer)); let receive_handle = scheduler.spawn(async_receive(async_reader)); loop_handle.run(None).expect("Failed to run event loop"); send_handle.join().expect("Send task failed"); receive_handle.join().expect("Receive task failed"); ``` -------------------------------- ### Initialize Async Executor and Scheduler Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-01-run-async-code.md Obtaining the executor and scheduler components required to manage async tasks within the event loop. ```rust {{#rustdoc_include async_example.rs:decl_executor}} ``` -------------------------------- ### Managing Event Sources Source: https://context7.com/smithay/calloop/llms.txt Explains how to use `RegistrationToken` to dynamically enable, disable, update, or remove event sources from the event loop. ```APIDOC ## Managing Event Sources Use `RegistrationToken` to enable, disable, update, or remove sources dynamically. ### Description This example demonstrates the lifecycle management of event sources within `calloop`. It shows how to obtain a token upon insertion, use it to disable and re-enable a source, and finally remove it entirely from the event loop. ### Method N/A (Example code, not an API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Code Example ```rust use calloop::EventLoop; use calloop::ping::make_ping; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (ping, ping_source) = make_ping()?; // Insert and get a token let token = handle.insert_source(ping_source, |(), _metadata, count| { *count += 1; println!("Ping! Count: {}", count); })?; let mut count = 0u32; // Ping and dispatch ping.ping(); event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After first ping: {}", count); // Disable the source handle.disable(&token)?; ping.ping(); event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After disabled ping: {}", count); // Still 1 // Re-enable the source handle.enable(&token)?; event_loop.dispatch(Some(Duration::ZERO), &mut count)?; println!("After re-enabled: {}", count); // Now 2 (pending ping delivered) // Remove the source completely handle.remove(token); Ok(()) } ``` ``` -------------------------------- ### Initialize ZeroMQ Event Source Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-03-creating-our-source-part-2-setup-methods.md A constructor function that converts a zmq::Socket into a ZeroMQSource, returning the source instance and an MPSC sender for message queuing. It initializes internal channels and generic file descriptor sources required for event loop integration. ```rust pub fn from_socket(socket: zmq::Socket) -> io::Result<(Self, calloop::channel::Sender)> { let (mpsc_sender, mpsc_receiver) = calloop::channel::channel(); let (wake_ping_sender, wake_ping_receiver) = calloop::ping::make_ping()?; let fd = socket.get_fd()?; let socket_source = calloop::generic::Generic::from_fd(fd, calloop::Interest::READ, calloop::Mode::Edge); Ok(( Self { socket, socket_source, mpsc_receiver, wake_ping_receiver, wake_ping_sender, }, mpsc_sender, )) } ``` -------------------------------- ### Monitor File Descriptors with Generic Event Source Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to monitor any AsFd-compliant file descriptor (like a UnixStream) for readiness. It uses the Generic source to handle read events and process data within the event loop. ```rust use calloop::{EventLoop, Interest, Mode, PostAction}; use calloop::generic::Generic; use std::io::{Read, Write}; use std::os::unix::net::UnixStream; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); let (mut writer, reader) = UnixStream::pair()?; let source = Generic::new(reader, Interest::READ, Mode::Level); handle.insert_source(source, |readiness, socket, buffer| { if readiness.readable { let mut buf = [0u8; 1024]; match (&**socket).read(&mut buf) { Ok(n) if n > 0 => { buffer.extend_from_slice(&buf[..n]); println!("Read {} bytes", n); } Ok(_) => println!("Connection closed"), Err(e) => println!("Read error: {}", e), } } Ok(PostAction::Continue) })?; writer.write_all(b"Hello, calloop!")?; writer.flush()?; let mut buffer = Vec::new(); event_loop.dispatch(Some(Duration::from_millis(100)), &mut buffer)?; println!("Received: {:?}", String::from_utf8_lossy(&buffer)); Ok(()) } ``` -------------------------------- ### ZeroMQ Event Source Implementation and Configuration Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-06-the-full-zeromq-event-source-code.md This snippet provides the Rust implementation for a ZeroMQ event source and the corresponding Cargo.toml dependency configuration. It requires the calloop, zmq, and anyhow crates to function correctly. ```rust {{#rustdoc_include zmqsource.rs}} ``` ```toml [dependencies] calloop = { path = '../..' } zmq = "0.9" anyhow = "1.0" ``` -------------------------------- ### Enable Calloop Futures-IO Feature Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-02-async-io-types.md To use Calloop's asynchronous IO capabilities, you need to enable the 'futures-io' feature in your Cargo.toml. It's also recommended to enable the 'executor' feature for seamless integration with async code. ```toml [dependencies.calloop] features = [ "futures-io" ] version = ... ``` -------------------------------- ### Generic File Descriptor Event Source Source: https://context7.com/smithay/calloop/llms.txt Monitor any file descriptor for readiness using the Generic event source, supporting sockets, pipes, and any type implementing AsFd. ```APIDOC ## Generic File Descriptor Event Source ### Description Allows monitoring of file descriptors (sockets, pipes) for readiness events (read/write) within the event loop. ### Method N/A (Rust API) ### Endpoint calloop::generic::Generic ### Parameters #### Request Body - **source** (AsFd) - Required - The file descriptor to monitor. - **interest** (Interest) - Required - Read or Write interest. - **mode** (Mode) - Required - Level or Edge triggered mode. ### Request Example let source = Generic::new(reader, Interest::READ, Mode::Level); ``` -------------------------------- ### Create a 5-second timer in Rust Source: https://github.com/smithay/calloop/blob/master/doc/src/ch02-02-timers.md Demonstrates how to create a timer that waits for a specified duration (5 seconds in this case) using the `calloop::timer::Timer` type. This timer will generate an event once the duration has elapsed. ```rust use std::time::Duration; use calloop::timer::Timer; // Create a timer that will expire in 5 seconds let timer = Timer::from_duration(Duration::from_secs(5)); ``` -------------------------------- ### Enable Calloop Executor Feature Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-01-run-async-code.md Configuration required in Cargo.toml to enable the executor functionality for async support. ```toml [dependencies.calloop] features = [ "executor" ] version = "..." ``` -------------------------------- ### Define ZeroMQSource Structure with Calloop Components Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-02-creating-our-source-part-1-our-types.md This Rust code defines the basic structure of the ZeroMQSource, including placeholders for calloop components like Generic, Channel, and PingSource. It outlines the initial fields required for integrating ZeroMQ with a calloop event loop. ```rust pub struct ZeroMQSource { // Calloop components. socket: calloop::generic::Generic>, mpsc_receiver: calloop::channel::Channel, wake_ping_receiver: calloop::ping::PingSource, } ``` -------------------------------- ### Accessing and Modifying Event Sources with Dispatcher Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to wrap an event source in a Dispatcher to maintain handle access after registration. This allows for dynamic modification of source interests and retrieval of the inner source object. ```rust use calloop::{EventLoop, Dispatcher, Interest, Mode, PostAction}; use calloop::generic::Generic; use std::os::unix::net::UnixStream; use std::io::Write; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop<()> = EventLoop::try_new()?; let handle = event_loop.handle(); let (mut tx, rx) = UnixStream::pair()?; let source = Generic::new(rx, Interest::READ, Mode::Level); let dispatcher = Dispatcher::new(source, |readiness, _socket, _data| { println!("Socket readable: {}", readiness.readable); Ok(PostAction::Continue) }); let token = handle.register_dispatcher(dispatcher.clone())?; { let source_ref = dispatcher.as_source_ref(); println!("Interest: {:?}", source_ref.interest); } { let mut source_mut = dispatcher.as_source_mut(); source_mut.interest = Interest::READ | Interest::WRITE; } handle.update(&token)?; tx.write_all(b"test")?; event_loop.dispatch(Some(Duration::from_millis(100)), &mut ())?; handle.remove(token); let source = dispatcher.into_source_inner(); let _rx = source.unwrap(); Ok(()) } ``` -------------------------------- ### Implement Synchronous Bounded Channel in Rust Source: https://context7.com/smithay/calloop/llms.txt Shows how to use a bounded synchronous channel to provide backpressure. The sender blocks when the channel capacity is reached, ensuring the producer does not overwhelm the event loop consumer. ```rust use calloop::EventLoop; use calloop::channel::{sync_channel, Event}; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let (sender, channel) = sync_channel::(2); handle.insert_source(channel, |event, _metadata, count| { if let Event::Msg(value) = event { *count += value; println!("Received: {}, total: {}", value, count); } })?; thread::spawn(move || { for i in 1..=10 { println!("Sending {}", i); sender.send(i).unwrap(); } }); let mut count = 0u32; while count < 55 { event_loop.dispatch(Some(Duration::from_millis(50)), &mut count)?; } Ok(()) } ``` -------------------------------- ### Handle Unix Signals on Linux Source: https://context7.com/smithay/calloop/llms.txt Shows how to receive and process Unix signals like SIGINT and SIGTERM within the event loop. This requires the 'signals' feature and is specific to Linux environments. ```rust #[cfg(all(target_os = "linux", feature = "signals"))] use calloop::EventLoop; #[cfg(all(target_os = "linux", feature = "signals"))] use calloop::signals::{Signal, Signals}; use std::time::Duration; #[cfg(all(target_os = "linux", feature = "signals"))] fn main() -> Result<(), Box> { let mut event_loop: EventLoop = EventLoop::try_new()?; let handle = event_loop.handle(); let signals = Signals::new(&[Signal::SIGINT, Signal::SIGTERM])?; handle.insert_source(signals, |event, _metadata, should_stop| { match event.signal() { Signal::SIGINT => { println!("Received SIGINT (Ctrl+C)"); *should_stop = true; } Signal::SIGTERM => { println!("Received SIGTERM"); *should_stop = true; } sig => println!("Received signal: {:?}", sig), } })?; let mut should_stop = false; println!("Press Ctrl+C to stop..."); while !should_stop { event_loop.dispatch(Some(Duration::from_millis(100)), &mut should_stop)?; } Ok(()) } ``` -------------------------------- ### Create Timeout Futures Source: https://context7.com/smithay/calloop/llms.txt Shows how to create futures that resolve after a specified duration using the event loop's timer system. Requires the 'block_on' feature. ```rust #[cfg(feature = "block_on")] use calloop::EventLoop; #[cfg(feature = "block_on")] use calloop::timer::TimeoutFuture; use std::time::Duration; #[cfg(feature = "block_on")] fn main() -> Result<(), Box> { let mut event_loop: EventLoop<()> = EventLoop::try_new()?; let handle = event_loop.handle(); let timeout = TimeoutFuture::from_duration(&handle, Duration::from_millis(500)); println!("Waiting for timeout..."); let result = event_loop.block_on( async { timeout.await; println!("Timeout elapsed!"); 42 }, &mut (), |_| {}, )?; println!("Result: {:?}", result); Ok(()) } ``` -------------------------------- ### Schedule Idle Callbacks Source: https://context7.com/smithay/calloop/llms.txt Demonstrates scheduling one-shot callbacks that execute after all pending events are processed. Includes logic for inserting and cancelling idle tasks. ```rust use calloop::EventLoop; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); handle.insert_idle(|messages| { messages.push("First idle"); }); handle.insert_idle(|messages| { messages.push("Second idle"); }); let idle = handle.insert_idle(|messages| { messages.push("This won't run"); }); idle.cancel(); handle.insert_idle(|messages| { messages.push("Third idle"); }); let mut messages = Vec::new(); event_loop.dispatch(Some(Duration::ZERO), &mut messages)?; println!("Messages: {:?}", messages); Ok(()) } ``` -------------------------------- ### Execute Async Futures in Event Loop Source: https://context7.com/smithay/calloop/llms.txt Explains how to run asynchronous futures by integrating an executor into the event loop. This requires the 'executor' feature and allows scheduling tasks that return results to the event loop. ```rust #[cfg(feature = "executor")] use calloop::EventLoop; #[cfg(feature = "executor")] use calloop::sources::futures::executor; use std::time::Duration; #[cfg(feature = "executor")] fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); let (exec, scheduler) = executor::()?; handle.insert_source(exec, |result, _metadata, results| { println!("Future completed with: {}", result); results.push(result); })?; scheduler.schedule(async { 42 })?; scheduler.schedule(async { 100 })?; scheduler.schedule(async { 10 + 20 })?; let mut results = Vec::new(); while results.len() < 3 { event_loop.dispatch(Some(Duration::from_millis(10)), &mut results)?; } println!("All results: {:?}", results); Ok(()) } ``` -------------------------------- ### Execute Event Loop Source: https://github.com/smithay/calloop/blob/master/doc/src/ch03-01-run-async-code.md Running the event loop to process scheduled async tasks and events. ```rust {{#rustdoc_include async_example.rs:run_loop}} ``` -------------------------------- ### Implement EventSource Lifecycle Methods Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-03-creating-our-source-part-2-setup-methods.md Implementation of the register, reregister, and unregister methods for an event source. These methods delegate lifecycle management to internal components and trigger manual wake-ups to handle edge-triggered socket events. ```rust fn register( &mut self, poll: &mut calloop::Poll, token_factory: &mut calloop::TokenFactory ) -> calloop::Result<()> { self.socket_source.register(poll, token_factory)?; self.mpsc_receiver.register(poll, token_factory)?; self.wake_ping_receiver.register(poll, token_factory)?; self.wake_ping_sender.ping(); Ok(()) } fn reregister( &mut self, poll: &mut calloop::Poll, token_factory: &mut calloop::TokenFactory ) -> calloop::Result<()> { self.socket_source.reregister(poll, token_factory)?; self.mpsc_receiver.reregister(poll, token_factory)?; self.wake_ping_receiver.reregister(poll, token_factory)?; self.wake_ping_sender.ping(); Ok(()) } fn unregister(&mut self, poll: &mut calloop::Poll)-> calloop::Result<()> { self.socket_source.unregister(poll)?; self.mpsc_receiver.unregister(poll)?; self.wake_ping_receiver.unregister(poll)?; Ok(()) } ``` -------------------------------- ### Idle Callbacks Source: https://context7.com/smithay/calloop/llms.txt Shows how to schedule one-shot callbacks that execute after all pending events in the event loop have been processed. ```APIDOC ## Idle Callbacks Schedule one-shot callbacks to run after all pending events are processed. ### Description This example demonstrates the use of `handle.insert_idle()` to schedule functions that will be executed once all other events for the current dispatch cycle have been handled. It also shows how to cancel an idle callback before it runs. ### Method N/A (Example code, not an API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Code Example ```rust use calloop::EventLoop; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); // Insert idle callbacks - they run after all events are processed handle.insert_idle(|messages| { messages.push("First idle"); }); handle.insert_idle(|messages| { messages.push("Second idle"); }); // This idle can be cancelled let idle = handle.insert_idle(|messages| { messages.push("This won't run"); }); idle.cancel(); handle.insert_idle(|messages| { messages.push("Third idle"); }); let mut messages = Vec::new(); // Dispatch to run idle callbacks event_loop.dispatch(Some(Duration::ZERO), &mut messages)?; println!("Messages: {:?}", messages); // Output: ["First idle", "Second idle", "Third idle"] Ok(()) } ``` ``` -------------------------------- ### Async Code Execution Flow Source: https://github.com/smithay/calloop/blob/master/doc/src/ch01-00-how-an-event-loop-works.md Illustrates a sequential execution flow in asynchronous programming where operations are awaited one after another. This highlights the state management differences compared to event-driven approaches. ```rust do_thing_one().await; do_thing_two().await; do_thing_three().await; ``` -------------------------------- ### Full Event Processing Function with Calloop (Rust) Source: https://github.com/smithay/calloop/blob/master/doc/src/ch04-05-creating-our-source-part-4-processing-events-really.md The complete `process_events` function integrating multiple event sources: a wake-up ping receiver, an MPSC channel for messages, and the ZeroMQ socket. It ensures all pending events are handled, including ZeroMQ socket readiness for sending and receiving, and manages message queuing. This function is designed to be used with the Calloop event loop. ```rust fn process_events( &mut self, readiness: calloop::Readiness, token: calloop::Token, mut callback: F, ) -> Result where F: FnMut(Self::Event, &mut Self::Metadata) -> Self::Ret, { // Runs if we were woken up on startup/registration. self.wake_ping_receiver .process_events(readiness, token, |_, _| {})?; // Runs if we were woken up because a message was sent on the channel. let outbox = &mut self.outbox; self.mpsc_receiver .process_events(readiness, token, |evt, _| { if let calloop::channel::Event::Msg(msg) = evt { outbox.push_back(msg); } })?; // Always process any pending zsocket events. let events = self .socket .get_events() .context("Failed to read ZeroMQ events")?; if events.contains(zmq::POLLOUT) { if let Some(parts) = self.outbox.pop_front() { self.socket .send_multipart(parts, 0) .context("Failed to send message")?; } } if events.contains(zmq::POLLIN) { let messages = self.socket .recv_multipart(0) .context("Failed to receive message")?; callback(messages, &mut ()) .context("Error in event callback")?; } Ok(calloop::PostAction::Continue) } ``` -------------------------------- ### Channel Event Source (MPSC) Source: https://context7.com/smithay/calloop/llms.txt Demonstrates using an asynchronous unbounded channel to send messages from other threads to the Calloop event loop. The sender can be cloned and sent across threads. ```APIDOC ## Channel Event Source (MPSC) Channels allow sending messages to the event loop from other threads. The `Sender` can be cloned and sent across threads, while the `Channel` receives messages as events. ### Method Not applicable (Rust example demonstrating library usage) ### Endpoint Not applicable (Rust example demonstrating library usage) ### Parameters Not applicable ### Request Example Not applicable ### Response Not applicable ### Example Usage (Rust) ```rust use calloop::EventLoop; use calloop::channel::{channel, sync_channel, Event}; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); // Create an async channel (unbounded) let (sender, channel) = channel::(); // Insert the channel as an event source handle.insert_source(channel, |event, _metadata, messages| { match event { Event::Msg(msg) => { println!("Received: {}", msg); messages.push(msg); } Event::Closed => { println!("Channel closed"); } } })?; // Clone sender for use in another thread let sender_clone = sender.clone(); // Spawn a thread that sends messages thread::spawn(move || { for i in 0..5 { sender_clone.send(format!("Message {}", i)).unwrap(); thread::sleep(Duration::from_millis(50)); } }); // Send from main thread too sender.send("Hello from main".to_string())?; let mut messages = Vec::new(); // Process messages for _ in 0..10 { event_loop.dispatch(Some(Duration::from_millis(100)), &mut messages)?; } println!("Received {} messages", messages.len()); Ok(()) } ``` ``` -------------------------------- ### Implement MPSC Channel Event Source in Rust Source: https://context7.com/smithay/calloop/llms.txt Demonstrates how to use an unbounded MPSC channel to send messages from multiple threads to the main event loop. The sender can be cloned across threads, and the channel acts as an event source that triggers callbacks upon message receipt. ```rust use calloop::EventLoop; use calloop::channel::{channel, sync_channel, Event}; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let mut event_loop: EventLoop> = EventLoop::try_new()?; let handle = event_loop.handle(); let (sender, channel) = channel::(); handle.insert_source(channel, |event, _metadata, messages| { match event { Event::Msg(msg) => { println!("Received: {}", msg); messages.push(msg); } Event::Closed => { println!("Channel closed"); } } })?; let sender_clone = sender.clone(); thread::spawn(move || { for i in 0..5 { sender_clone.send(format!("Message {}", i)).unwrap(); thread::sleep(Duration::from_millis(50)); } }); sender.send("Hello from main".to_string())?; let mut messages = Vec::new(); for _ in 0..10 { event_loop.dispatch(Some(Duration::from_millis(100)), &mut messages)?; } println!("Received {} messages", messages.len()); Ok(()) } ```