1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
/// Executor agnostic task spawning use core::future::Future; use core::pin::Pin; use parking_lot::{const_rwlock, RwLock}; type Spawner = fn(Pin<Box<dyn Future<Output = ()> + Send>>); static SPAWNER: RwLock<Option<Spawner>> = const_rwlock(None); /// Register a spawner. /// /// ```rust /// # use core::future::Future; /// # use core::pin::Pin; /// #[async_std::main] /// async fn main() { /// fn async_std_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { /// async_std::task::spawn(future); /// } /// async_spawn::register_spawner(async_std_spawn); /// async_spawn::spawn(async { /// println!("spawned on async-std"); /// }); /// } /// ``` /// /// ```rust /// # use core::future::Future; /// # use core::pin::Pin; /// #[tokio::main] /// async fn main() { /// fn tokio_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { /// tokio::spawn(future); /// } /// async_spawn::register_spawner(tokio_spawn); /// async_spawn::spawn(async { /// println!("spawned on tokio"); /// }); /// } /// ``` pub fn register_spawner(spawner: Spawner) { let mut lock = SPAWNER.write(); if lock.is_some() { panic!("async_spawn: spawner already registered"); } *lock = Some(spawner); } /// Spawn a task. /// /// ```rust /// # use core::future::Future; /// # use core::pin::Pin; /// #[async_std::main] /// async fn main() { /// fn async_std_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { /// async_std::task::spawn(future); /// } /// async_spawn::register_spawner(async_std_spawn); /// async_spawn::spawn(async { /// println!("spawned on async-std"); /// }); /// } /// ``` /// /// ```rust /// # use core::future::Future; /// # use core::pin::Pin; /// #[tokio::main] /// async fn main() { /// fn tokio_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { /// tokio::spawn(future); /// } /// async_spawn::register_spawner(tokio_spawn); /// async_spawn::spawn(async { /// println!("spawned on tokio"); /// }); /// } /// ``` pub fn spawn<F>(future: F) where F: Future<Output = ()> + Send + 'static, { SPAWNER.read().expect("async_spawn: no spawner registered")(Box::pin(future)); } #[cfg(test)] mod tests { use super::*; #[async_std::test] async fn test_async_std() { fn async_std_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { async_std::task::spawn(future); } register_spawner(async_std_spawn); spawn(async { println!("spawned on async-std"); }); } #[tokio::test] async fn test_tokio() { fn tokio_spawn(future: Pin<Box<dyn Future<Output = ()> + Send>>) { tokio::spawn(future); } register_spawner(tokio_spawn); spawn(async { println!("spawned on tokio"); }); } }