executor-core
A flexible task executor abstraction layer for Rust async runtimes.
Overview
executor-core
provides unified traits and type-erased wrappers for different async executors in Rust. It allows you to write code that's agnostic to the underlying executor implementation, whether you're using Tokio, async-executor, or custom executors.
Write async libraries without choosing a runtime. Your users should decide whether to use tokio, async-executor, or any other runtime. Not you.
Features
-
Zero-cost Executor Abstraction: Unified
Executor
andLocalExecutor
traits, using GAT to prevent unnecessary heap allocation and dynamic dispatch. -
Type Erasure:
AnyExecutor
andAnyLocalExecutor
for runtime flexibility -
Multiple Runtime Support:
- Tokio: Integration with Tokio runtime and LocalSet
- async-executor: Support for async-executor crate
- Web/WASM: Browser-compatible executor for web applications
-
Task Management: Rich task API with cancellation and error handling
-
No-std Compatible: Core functionality works in no-std environments
-
Panic Safety: Proper panic handling and propagation
How It Works
Instead of hard-coding tokio::spawn
, accept an executor parameter:
use Executor;
pub async
Users call it with their runtime:
// tokio users
let runtime = new?;
let sum = parallel_sum.await;
// async-executor users
let executor = new;
let sum = parallel_sum.await;
Quick Start
Add to your Cargo.toml
:
[]
= "0.3"
Basic Usage
use ;
use DefaultExecutor;
async
Using Different Executors
use ;
// Tokio executor
let tokio_executor = new;
let task = tokio_executor.spawn;
// Type-erased executor
let any_executor = new;
let task = any_executor.spawn;
Local Executors (Non-Send Futures)
use ;
use DefaultExecutor;
async
Task Cancellation
use ;
let executor = new;
let task = executor.spawn;
// Cancel the task
task.cancel.await;
Error Handling
use ;
let executor = new;
let task = executor.spawn;
// Handle task result with error
match task.result.await
Runtime Support
Tokio
[]
= { = "0.3", = ["tokio"] }
use ;
// Global executor
let executor = new;
// Or use Tokio runtime directly
let runtime = new.unwrap;
let task = runtime.spawn;
async-executor
[]
= { = "0.3", = ["async-executor"] }
use AsyncTask;
let executor = new;
let task: = executor.spawn;
Web/WASM
[]
= { = "0.3", = ["web"] }
use WebExecutor;
let executor = new;
let task = executor.spawn;
Feature Flags
std
- Enable std functionality (enabled by default)tokio
- Tokio runtime support (enabled by default)async-executor
- async-executor support (enabled by default)web
- Web/WASM support (enabled by default)full
- Enable all features
Architecture
The crate is built around two main traits:
Executor
: For spawningSend + 'static
futuresLocalExecutor
: For spawning'static
futures (not necessarilySend
)
Both traits produce tasks that implement the Task
trait, providing:
Future
implementation for awaiting resultspoll_result()
for explicit error handlingpoll_cancel()
for task cancellation
Type-erased versions (AnyExecutor
, AnyLocalExecutor
) allow runtime executor selection.
No-std Support
Core functionality works in no-std
environments:
[]
= { = "0.3", = false }
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.