Real-time compute-focused async executor with job pools, thread-local data, and priorities.
use switchyard::Switchyard;
use switchyard::threads::{thread_info, single_pool_one_to_one};
// Create a new switchyard with one job pool and empty thread local data
let yard = Switchyard::new(1, single_pool_one_to_one(thread_info(), Some("thread-name")), ||()).unwrap();
// Spawn a task on pool 0 and priority 10 and get a JoinHandle
let handle = yard.spawn(0, 10, async move { 5 + 5 });
// Spawn a lower priority task on the same pool
let handle2 = yard.spawn(0, 0, async move { 2 + 2 });
// Wait on the results
assert_eq!(handle.await + handle2.await, 14);
Switchyard is different from other existing async executors, focusing on situations where precise control of threads and execution order is needed. One such situation is using task parallelism to parallelize a compute workload.
Each task has a priority and tasks are ran in order from high priority to low priority.
// Spawn task with lowest priority.
yard.spawn(0, 0, async move { /* ... */ });
// Spawn task with higher priority. If both tasks are waiting, this one will run first.
yard.spawn(0, 10, async move { /* ... */ });
Inside each yard there can be multiple (up to [MAX_POOLS
]) different "job pools". Each thread in
the pool is dedicated to a single pool. By having multiple pools, it can help prevent executor
exhaustion.
// Create a yard with two job pools. Each logical core gets two threads, one per pool.
let yard = Switchyard::new(2, double_pool_two_to_one(thread_info(), Some("thread-name")), ||()).unwrap();
// Spawn task on pool 0.
yard.spawn(0, 0, async move { /* ... */ });
// Spawn task on pool 1.
yard.spawn(1, 0, async move { /* ... */ });
Each yard has some thread local data that can be accessed using spawn_local
.
Both the thread local data and the future generated by the async function passed to spawn_local
may be !Send
and !Sync
. The future will only be resumed on the thread that created it.
If the data is Send
, then you can call access_per_thread_data
to get
a vector of mutable references to all thread's data. See it's documentation for more information.
// Create yard with thread local data. The data is !Sync.
let yard = Switchyard::new(1, single_pool_one_to_one(thread_info(), Some("thread-name")), || Cell::new(42)).unwrap();
// Spawn task that uses thread local data. Each running thread will get their own copy.
yard.spawn_local(0, 0, |data| async move { data.set(10) });
1.51
Future MSRV bumps will be breaking changes.
License: MIT OR Apache-2.0 OR Zlib