### Basic Usage with Tokio Global Executor (Rust) Source: https://github.com/lexoliu/executor-core/blob/main/README.md This snippet shows how to initialize a Tokio runtime, set it as the global executor for `executor-core`, spawn a task using the `spawn` function, and then block until the task completes to get its result. Dependencies: `executor-core`, `tokio`. ```rust use executor_core::{Executor, init_global_executor, spawn}; use executor_core::tokio::Runtime; fn main() { // Initialize the global executor let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); init_global_executor(runtime); // Spawn a task let task = spawn(async { println!("Hello from spawned task!"); 42 }); let result = handle.block_on(task); println!("Task result: {}", result); } ``` -------------------------------- ### Spawn Tasks with Generic Executor (Rust) Source: https://github.com/lexoliu/executor-core/blob/main/README.md This example demonstrates how to write an asynchronous function that accepts any type implementing the `Executor` trait. It spawns two tasks using the provided executor and sums their results. This promotes runtime-agnostic library design. Dependencies: `executor-core`. ```rust use executor_core::Executor; pub async fn parallel_sum( executor: &E, numbers: Vec ) -> i32 { let (left, right) = numbers.split_at(numbers.len() / 2); let left_sum = executor.spawn(async move { left.iter().sum::() }); let right_sum = executor.spawn(async move { right.iter().sum::() }); left_sum.await + right_sum.await } ``` -------------------------------- ### Local Task Execution with Tokio LocalSet (Rust) Source: https://github.com/lexoliu/executor-core/blob/main/README.md This example demonstrates spawning a local task (a future that is not `Send`) using `LocalExecutor` within a Tokio `LocalSet`. This is useful when dealing with types like `std::rc::Rc` that cannot be sent across threads. Dependencies: `executor-core`, `tokio`. ```rust use executor_core::LocalExecutor; use executor_core::tokio::{LocalSet, Runtime}; let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); let local_set = LocalSet::new(); // Run the local executor inside the Tokio runtime let result = handle.block_on(local_set.run_until(async { let task = LocalExecutor::spawn_local(&local_set, async { // This future doesn't need to be Send let local_data = std::rc::Rc::new(42); *local_data }); task.await })); println!("Local task result: {}", result); ``` -------------------------------- ### Global and Local Executor Initialization and Spawning Source: https://context7.com/lexoliu/executor-core/llms.txt Shows how to initialize global and local executors using `init_global_executor` and `init_local_executor`, and then spawn tasks using the convenient `spawn` and `spawn_local` functions. ```rust use executor_core::{init_global_executor, spawn, init_local_executor, spawn_local}; use executor_core::tokio::{Runtime, LocalSet}; fn main() { // Initialize global executor let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); init_global_executor(runtime); // Spawn tasks globally let task = spawn(async { println!("Running on global executor"); 42 }); let result = handle.block_on(task); println!("Result: {}", result); // Output: 42 // Initialize local executor on current thread handle.block_on(async { let local_set = LocalSet::new(); init_local_executor(local_set); let local_task = spawn_local(async { let non_send = std::rc::Rc::new("local data"); format!("Value: {}", non_send) }); let local_result = local_task.await; println!("{}", local_result); // Output: Value: local data }); } ``` -------------------------------- ### Spawning Tasks with Tokio and Async-Executor (Rust) Source: https://github.com/lexoliu/executor-core/blob/main/README.md Illustrates spawning tasks using both Tokio and async-executor runtimes, demonstrating the executor-agnostic nature of `executor-core`. It also shows how to use `AnyExecutor` for runtime-agnostic storage. Dependencies: `executor-core`, `tokio`, `async-executor`, `futures-lite`. ```rust use executor_core::Executor; // Tokio executor let runtime = tokio::runtime::Runtime::new()?; let tokio_task = Executor::spawn(&runtime, async { "tokio result" }); let tokio_out = runtime.block_on(tokio_task); // async-executor let executor = async_executor::Executor::new(); let async_task = Executor::spawn(&executor, async { "async-executor result" }); let async_out = futures_lite::future::block_on(executor.run(async_task)); // Type-erased executor for runtime-agnostic storage let any_executor = executor_core::AnyExecutor::new(runtime); let erased_task = any_executor.spawn(async { 99u8 }); ``` -------------------------------- ### Tokio Runtime Integration with executor-core in Rust Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates direct integration with the Tokio runtime using `executor-core`. It shows spawning tasks with full panic safety and executing multiple concurrent tasks using `tokio::join!`. Requires `executor_core` and `tokio` crates. ```rust use executor_core::Executor; use executor_core::tokio::{Runtime, TokioTask}; #[tokio::main] async fn main() { // Use Tokio runtime directly let runtime = Runtime::new().unwrap(); let task: TokioTask<_> = Executor::spawn(&runtime, async { tokio::time::sleep(tokio::time::Duration::from_millis(10)).await; "task completed" }); let result = runtime.block_on(task); println!("{}", result); // Output: task completed // Spawn multiple concurrent tasks let task1 = runtime.spawn(async { 1 + 1 }); let task2 = runtime.spawn(async { 2 * 3 }); let task3 = runtime.spawn(async { 10 - 5 }); let (r1, r2, r3) = tokio::join!(task1, task2, task3); println!("Results: {}, {}, {}", r1, r2, r3); // Output: 2, 6, 5 } ``` -------------------------------- ### Spawning Tasks with async-executor and Executor-Core Source: https://github.com/lexoliu/executor-core/blob/main/README.md Illustrates how to spawn and execute tasks using the async-executor runtime with the executor-core crate. Ensure the 'async-executor' feature is enabled for this functionality. ```toml [dependencies] executor-core = { version = "0.6", features = ["async-executor"] } ``` ```rust use executor_core::AsyncTask; use executor_core::Executor; let executor = async_executor::Executor::new(); let task: AsyncTask<_> = Executor::spawn(&executor, async { "async-executor" }); let output = futures_lite::future::block_on(executor.run(task)); ``` -------------------------------- ### Spawning Tokio Tasks with Executor-Core Source: https://github.com/lexoliu/executor-core/blob/main/README.md Demonstrates how to spawn and manage tasks using the Tokio runtime directly with the executor-core crate. This requires the 'tokio' feature to be enabled. ```toml [dependencies] executor-core = { version = "0.6", features = ["tokio"] } ``` ```rust use executor_core::tokio::TokioTask; use executor_core::Executor; // Use Tokio runtime directly let runtime = tokio::runtime::Runtime::new().unwrap(); let task: TokioTask<_> = Executor::spawn(&runtime, async { "direct runtime usage" }); let output = runtime.block_on(task); ``` -------------------------------- ### Global and Local Executor Initialization Source: https://context7.com/lexoliu/executor-core/llms.txt Functions to initialize global or thread-local executors, allowing tasks to be spawned without explicitly passing an executor instance. ```APIDOC ## Global and Local Executor Initialization ### Description Initialize global or thread-local executors for convenient task spawning without needing to pass an `Executor` or `LocalExecutor` instance explicitly. ### Functions - `init_global_executor(executor)`: Initializes the global executor. - `spawn(future)`: Spawns a task on the global executor. - `init_local_executor(executor)`: Initializes the local executor for the current thread. - `spawn_local(future)`: Spawns a task on the local executor. ### Request Example ```rust use executor_core::{init_global_executor, spawn, init_local_executor, spawn_local}; use executor_core::tokio::{Runtime, LocalSet}; fn main() { // Initialize global executor let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); init_global_executor(runtime); // Spawn tasks globally let task = spawn(async { println!("Running on global executor"); 42 }); let result = handle.block_on(task); println!("Result: {}", result); // Output: 42 // Initialize local executor on current thread handle.block_on(async { let local_set = LocalSet::new(); init_local_executor(local_set); let local_task = spawn_local(async { let non_send = std::rc::Rc::new("local data"); format!("Value: {}", non_send) }); let local_result = local_task.await; println!("{}", local_result); // Output: Value: local data }); } ``` ### Response #### Success Response (200) Tasks are spawned and executed. The `spawn` and `spawn_local` functions return `Task` handles that can be awaited. #### Response Example ```rust // See Request Example for integrated usage. ``` ``` -------------------------------- ### async-executor Integration with executor-core in Rust Source: https://context7.com/lexoliu/executor-core/llms.txt Explains how to integrate the `async-executor` crate with `executor-core` using a unified API. Covers spawning both `Send` futures with `AsyncExecutor` and non-`Send` futures with `AsyncLocalExecutor`. Requires `executor_core` and `async-executor` crates. ```rust use executor_core::{Executor, LocalExecutor}; use executor_core::async_executor::{AsyncExecutor, AsyncLocalExecutor}; use executor_core::AsyncTask; use std::rc::Rc; fn main() { // Create async-executor let executor = AsyncExecutor::new(); // Spawn Send futures let task: AsyncTask<_> = Executor::spawn(&executor, async { futures_lite::future::yield_now().await; 42 }); let result = futures_lite::future::block_on(executor.run(task)); println!("Result: {}", result); // Output: 42 // Use local executor for non-Send futures let local_executor = AsyncLocalExecutor::new(); let local_task: AsyncTask<_> = LocalExecutor::spawn_local(&local_executor, async { let data = Rc::new("local data"); format!("Value: {}", data) }); let local_result = futures_lite::future::block_on(local_executor.run(local_task)); println!("{}", local_result); // Output: Value: local data } ``` -------------------------------- ### Custom Executor Implementation (Rust) Source: https://context7.com/lexoliu/executor-core/llms.txt Illustrates how to implement the `Executor` trait for custom executor types. This allows integrating custom runtimes or wrappers with the executor-core library. ```rust use executor_core::{Executor, Task}; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; // Custom executor wrapper struct MyExecutor { runtime: tokio::runtime::Runtime, } impl Executor for MyExecutor { type Task = MyTask; fn spawn(&self, fut: Fut) -> Self::Task where Fut: Future + Send + 'static, { let handle = self.runtime.spawn(fut); MyTask { handle } } } // Custom task wrapper struct MyTask { handle: tokio::task::JoinHandle, } impl Future for MyTask { type Output = T; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match Pin::new(&mut self.handle).poll(cx) { Poll::Ready(Ok(result)) => Poll::Ready(result), Poll::Ready(Err(err)) if err.is_panic() => { std::panic::resume_unwind(err.into_panic()) } Poll::Ready(Err(_)) => panic!("Task cancelled"), Poll::Pending => Poll::Pending, } } } impl Task for MyTask { fn poll_result( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll>> { match Pin::new(&mut self.handle).poll(cx) { Poll::Ready(Ok(result)) => Poll::Ready(Ok(result)), Poll::Ready(Err(err)) => { let error = if err.is_panic() { err.into_panic() } else { Box::new("Task cancelled") as Box }; Poll::Ready(Err(error)) } Poll::Pending => Poll::Pending, } } } fn main() { let my_executor = MyExecutor { runtime: tokio::runtime::Runtime::new().unwrap(), }; let task = my_executor.spawn(async { 42 }); let result = my_executor.runtime.block_on(task); println!("Result: {}", result); // Output: 42 } ``` -------------------------------- ### Task Error Handling with result() Method Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates explicit error handling for tasks, including catching panics, using the `result()` method on a `Task`. Shows how to differentiate between successful and failed tasks. ```rust use executor_core::{Executor, Task}; use executor_core::tokio::Runtime; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); // Task that panics let failing_task = runtime.spawn(async { panic!("Something went wrong!"); }); // Explicit error handling with result() match failing_task.result().await { Ok(value) => println!("Task completed: {}", value), Err(error) => { println!("Task panicked!"); if let Some(msg) = error.downcast_ref::<&str>() { println!("Panic message: {}", msg); } } } // Successful task let success_task = runtime.spawn(async { 100 }); match success_task.result().await { Ok(value) => println!("Success: {}", value), // Output: 100 Err(_) => println!("Failed"), } } ``` -------------------------------- ### Executor-Core No-std Support Configuration Source: https://github.com/lexoliu/executor-core/blob/main/README.md Configuration snippet for enabling no-std support in the executor-core crate by disabling default features. This is useful for environments without a standard library. ```toml [dependencies] executor-core = { version = "0.6", default-features = false } ``` -------------------------------- ### Detach Tasks for Background Execution in Rust Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates how to detach a task to run in the background without blocking the main thread. This is useful for fire-and-forget operations. Requires the `executor_core` and `tokio` crates. ```rust use executor_core::{init_global_executor, spawn}; use executor_core::tokio::Runtime; use std::time::Duration; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); init_global_executor(runtime); // Fire-and-forget background task let background_task = spawn(async { tokio::time::sleep(Duration::from_millis(100)).await; println!("Background work completed"); }); // Detach to run independently background_task.detach(); // Continue with other work immediately println!("Main thread continues without waiting"); // Give background task time to complete tokio::time::sleep(Duration::from_millis(200)).await; } ``` -------------------------------- ### Mailbox Pattern for Safe Cross-Thread Communication (Rust) Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates the Mailbox pattern for thread-safe access to a value using asynchronous message passing. It allows sending non-blocking updates and making asynchronous calls to retrieve or modify the value. ```rust use executor_core::mailbox::Mailbox; use executor_core::tokio::{LocalSet, Runtime}; use std::rc::Rc; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); let local_set = LocalSet::new(); handle.block_on(local_set.run_until(async { // Create mailbox with non-Send value let counter = Rc::new(std::cell::Cell::new(0)); let mailbox = Mailbox::new(&local_set, counter); // Send non-blocking updates from any thread mailbox.handle(|counter| { counter.set(counter.get() + 1); }); mailbox.handle(|counter| { counter.set(counter.get() + 10); }); // Make async call to get value let result = mailbox.call(|counter| counter.get()).await; println!("Counter value: {}", result); // Output: 11 // Multiple concurrent calls let val1 = mailbox.call(|counter| { counter.set(counter.get() * 2); counter.get() }).await; let val2 = mailbox.call(|counter| counter.get()).await; println!("Values: {}, {}", val1, val2); // Output: 22, 22 })); } ``` -------------------------------- ### Runtime-Agnostic Task Spawning with Executor Trait Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates spawning Send + 'static futures using the generic Executor trait, allowing for runtime-agnostic async functions. Works with any executor implementation. ```rust use executor_core::{Executor, Task}; // Write generic async functions that work with any executor pub async fn parallel_sum( executor: &E, numbers: Vec ) -> i32 { let (left, right) = numbers.split_at(numbers.len() / 2); let left_sum = executor.spawn(async move { left.iter().sum::() }); let right_sum = executor.spawn(async move { right.iter().sum::() }); left_sum.await + right_sum.await } // Tokio users can call with their runtime #[tokio::main] async fn main() { let runtime = tokio::runtime::Runtime::new().unwrap(); let sum = parallel_sum(&runtime, vec![1, 2, 3, 4, 5, 6]).await; println!("Sum: {}", sum); // Output: 21 } ``` -------------------------------- ### Task Error Handling and Detachment (Rust) Source: https://github.com/lexoliu/executor-core/blob/main/README.md This snippet shows how to handle potential panics within spawned tasks by using `task.result()`, which returns a `Result`. It also demonstrates how to detach a task using `detach()` when the result is not needed, allowing it to run in the background. Dependencies: `executor-core`, `tokio`. ```rust use executor_core::{Executor, init_global_executor, spawn, Task}; use executor_core::tokio::Runtime; let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); init_global_executor(runtime); let task = spawn(async { panic!("Something went wrong!"); }); match handle.block_on(task.result()) { Ok(value) => println!("Task completed: {}", value), Err(error) => println!("Task failed: {:?}", error), } // Detach when you don't need the result let fire_and_forget = spawn(async { 1 + 1 }); fire_and_forget.detach(); ``` -------------------------------- ### Task Error Handling Source: https://context7.com/lexoliu/executor-core/llms.txt Demonstrates how to handle task panics and errors explicitly using the `result()` method on the `Task` trait. ```APIDOC ## Task Error Handling ### Description Handle task panics and errors explicitly using the `Task` trait's `result()` method, which returns a `Result` containing either the successful output or the panic payload. ### Method `Task::result()` ### Endpoint N/A (Trait method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use executor_core::{Executor, Task}; use executor_core::tokio::Runtime; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); // Task that panics let failing_task = runtime.spawn(async { panic!("Something went wrong!"); }); // Explicit error handling with result() match failing_task.result().await { Ok(value) => println!("Task completed: {}", value), Err(error) => { println!("Task panicked!"); if let Some(msg) = error.downcast_ref::<&str>() { println!("Panic message: {}", msg); } } } // Successful task let success_task = runtime.spawn(async { 100 }); match success_task.result().await { Ok(value) => println!("Success: {}", value), // Output: 100 Err(_) => println!("Failed"), } } ``` ### Response #### Success Response (200) - **Ok(T)**: If the task completed successfully, contains the output value of type `T`. - **Err(Box)**: If the task panicked, contains the panic payload. #### Response Example ```rust // Output from the example: // Task panicked! // Panic message: Something went wrong! // Success: 100 ``` ``` -------------------------------- ### Executor Trait - Runtime-Agnostic Task Spawning Source: https://context7.com/lexoliu/executor-core/llms.txt The Executor trait offers a unified interface for spawning Send + 'static futures compatible with various async runtimes. ```APIDOC ## Executor Trait - Runtime-Agnostic Task Spawning ### Description Provides a unified interface for spawning `Send + 'static` futures across different async runtimes, enabling runtime-agnostic async code. ### Method `Executor::spawn` ### Endpoint N/A (Trait method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `future`: A `Future` that is `Send + 'static`. ### Request Example ```rust use executor_core::{Executor, Task}; pub async fn parallel_sum( executor: &E, numbers: Vec ) -> i32 { let (left, right) = numbers.split_at(numbers.len() / 2); let left_sum = executor.spawn(async move { left.iter().sum::() }); let right_sum = executor.spawn(async move { right.iter().sum::() }); left_sum.await + right_sum.await } ``` ### Response #### Success Response (200) Returns a `Task` handle that can be awaited to get the result of the spawned future. #### Response Example ```rust // Example usage with Tokio #[tokio::main] async fn main() { let runtime = tokio::runtime::Runtime::new().unwrap(); let sum = parallel_sum(&runtime, vec![1, 2, 3, 4, 5, 6]).await; println!("Sum: {}", sum); // Output: 21 } ``` ``` -------------------------------- ### Non-Send Future Support with LocalExecutor Trait Source: https://context7.com/lexoliu/executor-core/llms.txt Illustrates spawning futures that do not require Send, suitable for single-threaded executors, using the LocalExecutor trait. Demonstrates usage with Tokio's LocalSet. ```rust use executor_core::{LocalExecutor, Task}; use executor_core::tokio::{LocalSet, Runtime}; use std::rc::Rc; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); let local_set = LocalSet::new(); let result = handle.block_on(local_set.run_until(async { // Rc is not Send, but works with LocalExecutor let data = Rc::new(vec![1, 2, 3, 4, 5]); let task = LocalExecutor::spawn_local(&local_set, async move { data.iter().sum::() }); task.await })); println!("Local task result: {}", result); // Output: 15 } ``` -------------------------------- ### Type-Erased Executor with AnyExecutor in Rust Source: https://context7.com/lexoliu/executor-core/llms.txt Illustrates using `AnyExecutor` for type erasure, allowing different executor types (like Tokio Runtime) to be stored and managed generically. This enables runtime decisions on executor selection. Requires `executor_core` and `tokio` crates. ```rust use executor_core::{AnyExecutor, Executor}; use executor_core::tokio::Runtime; fn create_executor(use_tokio: bool) -> AnyExecutor { if use_tokio { let runtime = Runtime::new().unwrap(); AnyExecutor::new(runtime) } else { #[cfg(feature = "async-executor")] { let executor = async_executor::Executor::new(); AnyExecutor::new(executor) } #[cfg(not(feature = "async-executor"))] panic!("async-executor feature not enabled"); } } #[tokio::main] async fn main() { let any_executor = create_executor(true); // Spawn tasks on type-erased executor let task = any_executor.spawn(async { println!("Running on any executor"); 42 }); // Downcast back to concrete type if needed if let Some(runtime) = any_executor.downcast_ref::() { let result = runtime.block_on(task); println!("Result: {}", result); // Output: 42 } } ``` -------------------------------- ### Type-Erased Local Executor with AnyLocalExecutor in Rust Source: https://context7.com/lexoliu/executor-core/llms.txt Shows how to use `AnyLocalExecutor` for type erasure of local executors, suitable for non-`Send` futures. This provides runtime flexibility when dealing with futures that cannot be sent across threads. Requires `executor_core` and `tokio` crates. ```rust use executor_core::{AnyLocalExecutor, LocalExecutor}; use executor_core::tokio::{LocalSet, Runtime}; use std::rc::Rc; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); let any_local = AnyLocalExecutor::new(LocalSet::new()); handle.block_on(async { if let Some(local_set) = any_local.downcast_ref::() { local_set.run_until(async { // Spawn non-Send future on type-erased executor let non_send_data = Rc::new(vec![10, 20, 30]); let task = any_local.spawn_local(async move { non_send_data.iter().sum::() }); let result = task.await; println!("Result: {}", result); // Output: 60 }).await } }); } ``` -------------------------------- ### LocalExecutor Trait - Non-Send Future Support Source: https://context7.com/lexoliu/executor-core/llms.txt The LocalExecutor trait allows spawning futures that do not require `Send`, suitable for single-threaded executors. ```APIDOC ## LocalExecutor Trait - Non-Send Future Support ### Description Enables the spawning of futures that do not need to be `Send`, which is useful for single-threaded executors like `tokio::task::LocalSet`. ### Method `LocalExecutor::spawn_local` ### Endpoint N/A (Trait method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `future`: A future that does not require `Send`. ### Request Example ```rust use executor_core::{LocalExecutor, Task}; use executor_core::tokio::{LocalSet, Runtime}; use std::rc::Rc; #[tokio::main] async fn main() { let runtime = Runtime::new().unwrap(); let handle = runtime.handle().clone(); let local_set = LocalSet::new(); let result = handle.block_on(local_set.run_until(async { let data = Rc::new(vec![1, 2, 3, 4, 5]); let task = LocalExecutor::spawn_local(&local_set, async move { data.iter().sum::() }); task.await })); println!("Local task result: {}", result); // Output: 15 } ``` ### Response #### Success Response (200) Returns a `Task` handle that can be awaited to get the result of the spawned non-Send future. #### Response Example ```rust // See Request Example for integrated usage. ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.