1 use futures_task::{LocalSpawn, Spawn}; 2 3 #[cfg(feature = "compat")] 4 use crate::compat::Compat; 5 6 #[cfg(feature = "channel")] 7 #[cfg(feature = "std")] 8 use crate::future::{FutureExt, RemoteHandle}; 9 #[cfg(feature = "alloc")] 10 use alloc::boxed::Box; 11 #[cfg(feature = "alloc")] 12 use futures_core::future::Future; 13 #[cfg(feature = "alloc")] 14 use futures_task::{FutureObj, LocalFutureObj, SpawnError}; 15 16 impl<Sp: ?Sized> SpawnExt for Sp where Sp: Spawn {} 17 impl<Sp: ?Sized> LocalSpawnExt for Sp where Sp: LocalSpawn {} 18 19 /// Extension trait for `Spawn`. 20 pub trait SpawnExt: Spawn { 21 /// Spawns a task that polls the given future with output `()` to 22 /// completion. 23 /// 24 /// This method returns a [`Result`] that contains a [`SpawnError`] if 25 /// spawning fails. 26 /// 27 /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if 28 /// you want to spawn a future with output other than `()` or if you want 29 /// to be able to await its completion. 30 /// 31 /// Note this method will eventually be replaced with the upcoming 32 /// `Spawn::spawn` method which will take a `dyn Future` as input. 33 /// Technical limitations prevent `Spawn::spawn` from being implemented 34 /// today. Feel free to use this method in the meantime. 35 /// 36 /// ``` 37 /// # { 38 /// use futures::executor::ThreadPool; 39 /// use futures::task::SpawnExt; 40 /// 41 /// let executor = ThreadPool::new().unwrap(); 42 /// 43 /// let future = async { /* ... */ }; 44 /// executor.spawn(future).unwrap(); 45 /// # } 46 /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 47 /// ``` 48 #[cfg(feature = "alloc")] spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError> where Fut: Future<Output = ()> + Send + 'static,49 fn spawn<Fut>(&self, future: Fut) -> Result<(), SpawnError> 50 where 51 Fut: Future<Output = ()> + Send + 'static, 52 { 53 self.spawn_obj(FutureObj::new(Box::new(future))) 54 } 55 56 /// Spawns a task that polls the given future to completion and returns a 57 /// future that resolves to the spawned future's output. 58 /// 59 /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if 60 /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that 61 /// resolves to the output of the spawned future. 62 /// 63 /// ``` 64 /// # { 65 /// use futures::executor::{block_on, ThreadPool}; 66 /// use futures::future; 67 /// use futures::task::SpawnExt; 68 /// 69 /// let executor = ThreadPool::new().unwrap(); 70 /// 71 /// let future = future::ready(1); 72 /// let join_handle_fut = executor.spawn_with_handle(future).unwrap(); 73 /// assert_eq!(block_on(join_handle_fut), 1); 74 /// # } 75 /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 76 /// ``` 77 #[cfg(feature = "channel")] 78 #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] 79 #[cfg(feature = "std")] spawn_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError> where Fut: Future + Send + 'static, Fut::Output: Send,80 fn spawn_with_handle<Fut>(&self, future: Fut) -> Result<RemoteHandle<Fut::Output>, SpawnError> 81 where 82 Fut: Future + Send + 'static, 83 Fut::Output: Send, 84 { 85 let (future, handle) = future.remote_handle(); 86 self.spawn(future)?; 87 Ok(handle) 88 } 89 90 /// Wraps a [`Spawn`] and makes it usable as a futures 0.1 `Executor`. 91 /// Requires the `compat` feature to enable. 92 #[cfg(feature = "compat")] 93 #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] compat(self) -> Compat<Self> where Self: Sized,94 fn compat(self) -> Compat<Self> 95 where 96 Self: Sized, 97 { 98 Compat::new(self) 99 } 100 } 101 102 /// Extension trait for `LocalSpawn`. 103 pub trait LocalSpawnExt: LocalSpawn { 104 /// Spawns a task that polls the given future with output `()` to 105 /// completion. 106 /// 107 /// This method returns a [`Result`] that contains a [`SpawnError`] if 108 /// spawning fails. 109 /// 110 /// You can use [`spawn_with_handle`](SpawnExt::spawn_with_handle) if 111 /// you want to spawn a future with output other than `()` or if you want 112 /// to be able to await its completion. 113 /// 114 /// Note this method will eventually be replaced with the upcoming 115 /// `Spawn::spawn` method which will take a `dyn Future` as input. 116 /// Technical limitations prevent `Spawn::spawn` from being implemented 117 /// today. Feel free to use this method in the meantime. 118 /// 119 /// ``` 120 /// use futures::executor::LocalPool; 121 /// use futures::task::LocalSpawnExt; 122 /// 123 /// let executor = LocalPool::new(); 124 /// let spawner = executor.spawner(); 125 /// 126 /// let future = async { /* ... */ }; 127 /// spawner.spawn_local(future).unwrap(); 128 /// ``` 129 #[cfg(feature = "alloc")] spawn_local<Fut>(&self, future: Fut) -> Result<(), SpawnError> where Fut: Future<Output = ()> + 'static,130 fn spawn_local<Fut>(&self, future: Fut) -> Result<(), SpawnError> 131 where 132 Fut: Future<Output = ()> + 'static, 133 { 134 self.spawn_local_obj(LocalFutureObj::new(Box::new(future))) 135 } 136 137 /// Spawns a task that polls the given future to completion and returns a 138 /// future that resolves to the spawned future's output. 139 /// 140 /// This method returns a [`Result`] that contains a [`RemoteHandle`](crate::future::RemoteHandle), or, if 141 /// spawning fails, a [`SpawnError`]. [`RemoteHandle`](crate::future::RemoteHandle) is a future that 142 /// resolves to the output of the spawned future. 143 /// 144 /// ``` 145 /// use futures::executor::LocalPool; 146 /// use futures::task::LocalSpawnExt; 147 /// 148 /// let mut executor = LocalPool::new(); 149 /// let spawner = executor.spawner(); 150 /// 151 /// let future = async { 1 }; 152 /// let join_handle_fut = spawner.spawn_local_with_handle(future).unwrap(); 153 /// assert_eq!(executor.run_until(join_handle_fut), 1); 154 /// ``` 155 #[cfg(feature = "channel")] 156 #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] 157 #[cfg(feature = "std")] spawn_local_with_handle<Fut>( &self, future: Fut, ) -> Result<RemoteHandle<Fut::Output>, SpawnError> where Fut: Future + 'static,158 fn spawn_local_with_handle<Fut>( 159 &self, 160 future: Fut, 161 ) -> Result<RemoteHandle<Fut::Output>, SpawnError> 162 where 163 Fut: Future + 'static, 164 { 165 let (future, handle) = future.remote_handle(); 166 self.spawn_local(future)?; 167 Ok(handle) 168 } 169 } 170