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