2
2
3
3
use crate :: prelude:: * ;
4
4
use crate :: Cancellable ;
5
+ use futures_channel:: oneshot;
6
+ use futures_core:: Future ;
5
7
use glib:: { translate:: * , IsA } ;
6
8
use std:: num:: NonZeroU64 ;
7
9
@@ -62,6 +64,10 @@ pub trait CancellableExtManual {
62
64
/// operation is finished and the signal handler is removed.
63
65
#[ doc( alias = "g_cancellable_disconnect" ) ]
64
66
fn disconnect_cancelled ( & self , id : CancelledHandlerId ) ;
67
+ // rustdoc-stripper-ignore-next
68
+ /// Returns a `Future` that completes when the cancellable becomes cancelled. Completes
69
+ /// immediately if the cancellable is already cancelled.
70
+ fn future ( & self ) -> std:: pin:: Pin < Box < dyn Future < Output = ( ) > + Send + Sync + ' static > > ;
65
71
}
66
72
67
73
impl < O : IsA < Cancellable > > CancellableExtManual for O {
@@ -101,6 +107,19 @@ impl<O: IsA<Cancellable>> CancellableExtManual for O {
101
107
fn disconnect_cancelled ( & self , id : CancelledHandlerId ) {
102
108
unsafe { ffi:: g_cancellable_disconnect ( self . as_ptr ( ) as * mut _ , id. as_raw ( ) ) } ;
103
109
}
110
+ fn future ( & self ) -> std:: pin:: Pin < Box < dyn Future < Output = ( ) > + Send + Sync + ' static > > {
111
+ let cancellable = self . as_ref ( ) . clone ( ) ;
112
+ let ( tx, rx) = oneshot:: channel ( ) ;
113
+ let id = cancellable. connect_cancelled ( move |_| {
114
+ let _ = tx. send ( ( ) ) ;
115
+ } ) ;
116
+ Box :: pin ( async move {
117
+ rx. await . unwrap ( ) ;
118
+ if let Some ( id) = id {
119
+ cancellable. disconnect_cancelled ( id) ;
120
+ }
121
+ } )
122
+ }
104
123
}
105
124
106
125
#[ cfg( test) ]
@@ -114,4 +133,35 @@ mod tests {
114
133
c. cancel ( ) ; // if it doesn't crash at this point, then we're good to go!
115
134
c. disconnect_cancelled ( id. unwrap ( ) ) ;
116
135
}
136
+
137
+ #[ test]
138
+ fn cancellable_future ( ) {
139
+ let c = Cancellable :: new ( ) ;
140
+ c. cancel ( ) ;
141
+ glib:: MainContext :: new ( ) . block_on ( c. future ( ) ) ;
142
+ }
143
+
144
+ #[ test]
145
+ fn cancellable_future_thread ( ) {
146
+ let cancellable = Cancellable :: new ( ) ;
147
+ let c = cancellable. clone ( ) ;
148
+ std:: thread:: spawn ( move || c. cancel ( ) ) . join ( ) . unwrap ( ) ;
149
+ glib:: MainContext :: new ( ) . block_on ( cancellable. future ( ) ) ;
150
+ }
151
+
152
+ #[ test]
153
+ fn cancellable_future_delayed ( ) {
154
+ let ctx = glib:: MainContext :: new ( ) ;
155
+ let c = Cancellable :: new ( ) ;
156
+ let ( tx, rx) = oneshot:: channel ( ) ;
157
+ {
158
+ let c = c. clone ( ) ;
159
+ ctx. spawn_local ( async move {
160
+ c. future ( ) . await ;
161
+ tx. send ( ( ) ) . unwrap ( ) ;
162
+ } ) ;
163
+ }
164
+ std:: thread:: spawn ( move || c. cancel ( ) ) . join ( ) . unwrap ( ) ;
165
+ ctx. block_on ( rx) . unwrap ( ) ;
166
+ }
117
167
}
0 commit comments