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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#[ allow(unused_imports) ]
use
{
std :: { future::Future, sync::atomic::{ AtomicBool, Ordering } } ,
std :: { task::{ Poll, Context }, pin::Pin } ,
futures_util:: { future::{ AbortHandle, Aborted, RemoteHandle }, ready } ,
super :: *,
};
#[ cfg( feature = "async_global" ) ]
type BoxedFut<T> = Pin<Box< dyn Future<Output=T> + Send >>;
#[ derive( Debug ) ]
pub struct BlockingHandle<T>( InnerBh<T> );
impl<T> BlockingHandle<T>
{
#[ cfg(any( feature = "tokio_tp", feature = "tokio_ct" )) ]
pub fn tokio( handle: TokioJoinHandle<T> ) -> Self
{
Self( InnerBh::Tokio(handle) )
}
#[ cfg( feature = "async_global" ) ]
pub fn async_global( task: BoxedFut<T> ) -> Self
{
Self( InnerBh::AsyncGlobal(task) )
}
#[ cfg( feature = "async_std" ) ]
pub fn async_std( handle: AsyncStdJoinHandle<T> ) -> Self
{
Self( InnerBh::AsyncStd(handle) )
}
}
#[ allow(dead_code) ]
enum InnerBh<T>
{
#[ cfg(any( feature = "tokio_tp", feature = "tokio_ct" )) ]
Tokio( TokioJoinHandle<T> ),
#[ cfg( feature = "async_global" ) ]
AsyncGlobal( BoxedFut<T> ),
#[ cfg( feature = "async_std" ) ]
AsyncStd( AsyncStdJoinHandle<T> ),
Phantom( std::marker::PhantomData< fn()->T > ),
}
impl<T: 'static> Future for BlockingHandle<T>
{
type Output = T;
fn poll( self: Pin<&mut Self>, _cx: &mut Context<'_> ) -> Poll<Self::Output>
{
match &mut self.get_mut().0
{
#[ cfg(any( feature = "tokio_tp", feature = "tokio_ct" )) ]
InnerBh::Tokio(handle) =>
{
match ready!( Pin::new( handle ).poll( _cx ) )
{
Ok(t) => Poll::Ready( t ),
Err(e) => panic!( "Task has been canceled or has panicked. \
Are you dropping the executor to early? Error: {}", e ),
}
}
#[ cfg( feature = "async_std" ) ] InnerBh::AsyncStd ( handle ) => Pin::new( handle ).poll( _cx ) ,
#[ cfg( feature = "async_global" ) ] InnerBh::AsyncGlobal( task ) => Pin::new( task ).poll( _cx ) ,
InnerBh::Phantom(_) => unreachable!(),
}
}
}
impl<T> std::fmt::Debug for InnerBh<T>
{
fn fmt( &self, f: &mut std::fmt::Formatter<'_> ) -> std::fmt::Result
{
write!( f, "InnerBh" )
}
}