22
22
/// The handle to a remote future returned by
23
23
/// [`remote_handle`](crate::future::FutureExt::remote_handle). When you drop this,
24
24
/// the remote future will be woken up to be dropped by the executor.
25
+ ///
26
+ /// ## Unwind safety
27
+ ///
28
+ /// When the remote future panics, [Remote] will catch the unwind and transfer it to
29
+ /// the thread where `RemoteHandle` is being awaited. This is good for the common
30
+ /// case where [Remote] is spawned on a threadpool. It is unlikely that other code
31
+ /// in the executor working thread shares mutable data with the spawned future and we
32
+ /// preserve the executor from losing its working threads.
33
+ ///
34
+ /// If you run the future locally and send the handle of to be awaited elsewhere, you
35
+ /// must be careful with regard to unwind safety because the thread in which the future
36
+ /// is polled will keep running after the panic and the thread running the [RemoteHandle]
37
+ /// will unwind.
25
38
#[ must_use = "futures do nothing unless you `.await` or poll them" ]
26
39
#[ derive( Debug ) ]
27
40
pub struct RemoteHandle < T > {
@@ -45,7 +58,9 @@ impl<T: Send + 'static> Future for RemoteHandle<T> {
45
58
fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < T > {
46
59
match ready ! ( self . rx. poll_unpin( cx) ) {
47
60
Ok ( Ok ( output) ) => Poll :: Ready ( output) ,
61
+ // the remote future panicked.
48
62
Ok ( Err ( e) ) => panic:: resume_unwind ( e) ,
63
+ // The oneshot sender was dropped.
49
64
Err ( e) => panic:: resume_unwind ( Box :: new ( e) ) ,
50
65
}
51
66
}
@@ -101,9 +116,7 @@ pub(super) fn remote_handle<Fut: Future>(future: Fut) -> (Remote<Fut>, RemoteHan
101
116
let ( tx, rx) = oneshot:: channel ( ) ;
102
117
let keep_running = Arc :: new ( AtomicBool :: new ( false ) ) ;
103
118
104
- // AssertUnwindSafe is used here because `Send + 'static` is basically
105
- // an alias for an implementation of the `UnwindSafe` trait but we can't
106
- // express that in the standard library right now.
119
+ // Unwind Safety: See the docs for RemoteHandle.
107
120
let wrapped = Remote {
108
121
future : AssertUnwindSafe ( future) . catch_unwind ( ) ,
109
122
tx : Some ( tx) ,
0 commit comments