use anyspawn::{BoxedBlockingTask, BoxedFuture, SpawnCustom, Spawner};
use thread_aware::ThreadAware;
use thread_aware::affinity::{Affinity, pinned_affinities};
use thread_aware::closure::ThreadAwareAsyncFnOnce;
#[tokio::main]
async fn main() {
let spawner = Spawner::new_custom("per-core", Scheduler::default());
let _default = spawner.spawn(async { 1 + 1 }).await;
let affinities = pinned_affinities(&[1, 1]);
let mut relocated0 = spawner.clone();
relocated0.relocate(None, affinities[0]);
let _relocated0 = relocated0.spawn(async { 1 + 1 }).await;
let mut relocated1 = spawner.clone();
relocated1.relocate(None, affinities[1]);
let _relocated1 = relocated1.spawn(async { 1 + 1 }).await;
}
#[derive(Default, Clone)]
struct Scheduler(Option<usize>);
impl Scheduler {
fn caption(&self) -> String {
match self.0 {
Some(id) => format!("Scheduler ({id})"),
None => "Scheduler (default)".to_string(),
}
}
}
impl ThreadAware for Scheduler {
fn relocate(&mut self, _source: Option<Affinity>, destination: Affinity) {
self.0 = Some(destination.processor_index());
}
}
impl SpawnCustom for Scheduler {
fn spawn(&self, task: BoxedFuture) {
println!("{}: executing", self.caption());
tokio::spawn(task);
}
fn spawn_anywhere(&self, task: Box<dyn ThreadAwareAsyncFnOnce<()>>) {
self.spawn(task.call_once());
}
fn spawn_blocking(&self, task: BoxedBlockingTask) {
println!("{}: executing blocking", self.caption());
tokio::task::spawn_blocking(task);
}
}