1
1
extern crate std;
2
2
3
3
use {
4
+ super :: ErrorContext ,
4
5
super :: Handle ,
5
6
futures:: {
6
7
channel:: oneshot,
@@ -20,10 +21,10 @@ use {
20
21
#[ doc( hidden) ]
21
22
pub struct FutureVtable < T > {
22
23
pub write : fn ( future : u32 , value : T ) -> Pin < Box < dyn Future < Output = bool > > > ,
23
- pub read : fn ( future : u32 ) -> Pin < Box < dyn Future < Output = Option < T > > > > ,
24
+ pub read : fn ( future : u32 ) -> Pin < Box < dyn Future < Output = Option < Result < T , ErrorContext > > > > > ,
24
25
pub cancel_write : fn ( future : u32 ) ,
25
26
pub cancel_read : fn ( future : u32 ) ,
26
- pub close_writable : fn ( future : u32 ) ,
27
+ pub close_writable : fn ( future : u32 , err_ctx : u32 ) ,
27
28
pub close_readable : fn ( future : u32 ) ,
28
29
}
29
30
@@ -78,7 +79,8 @@ impl<T> CancelableWrite<T> {
78
79
Handle :: LocalOpen
79
80
| Handle :: LocalWaiting ( _)
80
81
| Handle :: Read
81
- | Handle :: LocalClosed => unreachable ! ( ) ,
82
+ | Handle :: LocalClosed
83
+ | Handle :: WriteClosedErr ( _) => unreachable ! ( ) ,
82
84
Handle :: LocalReady ( ..) => {
83
85
entry. insert ( Handle :: LocalOpen ) ;
84
86
}
@@ -126,7 +128,9 @@ impl<T> FutureWriter<T> {
126
128
Poll :: Pending
127
129
}
128
130
Handle :: LocalReady ( ..) => Poll :: Pending ,
129
- Handle :: LocalClosed => Poll :: Ready ( ( ) ) ,
131
+ Handle :: LocalClosed | Handle :: WriteClosedErr ( _) => {
132
+ Poll :: Ready ( ( ) )
133
+ }
130
134
Handle :: LocalWaiting ( _) | Handle :: Read | Handle :: Write => {
131
135
unreachable ! ( )
132
136
}
@@ -141,13 +145,29 @@ impl<T> FutureWriter<T> {
141
145
_ = tx. send ( Box :: new ( v) ) ;
142
146
Box :: pin ( future:: ready ( ( ) ) )
143
147
}
144
- Handle :: LocalClosed => Box :: pin ( future:: ready ( ( ) ) ) ,
148
+ Handle :: LocalClosed | Handle :: WriteClosedErr ( _ ) => Box :: pin ( future:: ready ( ( ) ) ) ,
145
149
Handle :: Read | Handle :: LocalReady ( ..) => unreachable ! ( ) ,
146
150
Handle :: Write => Box :: pin ( ( vtable. write ) ( handle, v) . map ( drop) ) ,
147
151
} ,
148
152
} ) ,
149
153
}
150
154
}
155
+
156
+ /// Close the writer with an error that will be returned as the last value
157
+ ///
158
+ /// Note that this error is not sent immediately, but only when the
159
+ /// writer closes, which is normally a result of a `drop()`
160
+ pub fn close_with_error ( & mut self , err : ErrorContext ) {
161
+ super :: with_entry ( self . handle , move |entry| match entry {
162
+ Entry :: Vacant ( _) => unreachable ! ( ) ,
163
+ Entry :: Occupied ( mut entry) => match entry. get_mut ( ) {
164
+ // Regardless of current state, put the writer into a closed with error state
165
+ _ => {
166
+ entry. insert ( Handle :: WriteClosedErr ( Some ( err) ) ) ;
167
+ }
168
+ } ,
169
+ } ) ;
170
+ }
151
171
}
152
172
153
173
impl < T > Drop for FutureWriter < T > {
@@ -161,8 +181,17 @@ impl<T> Drop for FutureWriter<T> {
161
181
Handle :: Read => unreachable ! ( ) ,
162
182
Handle :: Write | Handle :: LocalClosed => {
163
183
entry. remove ( ) ;
164
- ( self . vtable . close_writable ) ( self . handle ) ;
184
+ ( self . vtable . close_writable ) ( self . handle , 0 ) ;
165
185
}
186
+ Handle :: WriteClosedErr ( _) => match entry. remove ( ) {
187
+ Handle :: WriteClosedErr ( None ) => {
188
+ ( self . vtable . close_writable ) ( self . handle , 0 ) ;
189
+ }
190
+ Handle :: WriteClosedErr ( Some ( err_ctx) ) => {
191
+ ( self . vtable . close_writable ) ( self . handle , err_ctx. handle ( ) ) ;
192
+ }
193
+ _ => unreachable ! ( ) ,
194
+ } ,
166
195
} ,
167
196
} ) ;
168
197
}
@@ -171,13 +200,13 @@ impl<T> Drop for FutureWriter<T> {
171
200
/// Represents a read operation which may be canceled prior to completion.
172
201
pub struct CancelableRead < T : ' static > {
173
202
reader : Option < FutureReader < T > > ,
174
- future : Pin < Box < dyn Future < Output = Option < T > > > > ,
203
+ future : Pin < Box < dyn Future < Output = Option < Result < T , ErrorContext > > > > > ,
175
204
}
176
205
177
206
impl < T > Future for CancelableRead < T > {
178
- type Output = Option < T > ;
207
+ type Output = Option < Result < T , ErrorContext > > ;
179
208
180
- fn poll ( self : Pin < & mut Self > , cx : & mut Context ) -> Poll < Option < T > > {
209
+ fn poll ( self : Pin < & mut Self > , cx : & mut Context ) -> Poll < Option < Result < T , ErrorContext > > > {
181
210
let me = self . get_mut ( ) ;
182
211
match me. future . poll_unpin ( cx) {
183
212
Poll :: Ready ( v) => {
@@ -206,7 +235,8 @@ impl<T> CancelableRead<T> {
206
235
Handle :: LocalOpen
207
236
| Handle :: LocalReady ( ..)
208
237
| Handle :: Write
209
- | Handle :: LocalClosed => unreachable ! ( ) ,
238
+ | Handle :: LocalClosed
239
+ | Handle :: WriteClosedErr ( _) => unreachable ! ( ) ,
210
240
Handle :: LocalWaiting ( _) => {
211
241
entry. insert ( Handle :: LocalOpen ) ;
212
242
}
@@ -262,7 +292,8 @@ impl<T> FutureReader<T> {
262
292
| Handle :: LocalOpen
263
293
| Handle :: LocalReady ( ..)
264
294
| Handle :: LocalWaiting ( _)
265
- | Handle :: LocalClosed => {
295
+ | Handle :: LocalClosed
296
+ | Handle :: WriteClosedErr ( _) => {
266
297
unreachable ! ( )
267
298
}
268
299
} ,
@@ -286,7 +317,10 @@ impl<T> FutureReader<T> {
286
317
Handle :: Read | Handle :: LocalClosed => {
287
318
entry. remove ( ) ;
288
319
}
289
- Handle :: LocalReady ( ..) | Handle :: LocalWaiting ( _) | Handle :: Write => unreachable ! ( ) ,
320
+ Handle :: LocalReady ( ..)
321
+ | Handle :: LocalWaiting ( _)
322
+ | Handle :: Write
323
+ | Handle :: WriteClosedErr ( _) => unreachable ! ( ) ,
290
324
} ,
291
325
} ) ;
292
326
@@ -295,7 +329,7 @@ impl<T> FutureReader<T> {
295
329
}
296
330
297
331
impl < T > IntoFuture for FutureReader < T > {
298
- type Output = Option < T > ;
332
+ type Output = Option < Result < T , ErrorContext > > ;
299
333
type IntoFuture = CancelableRead < T > ;
300
334
301
335
/// Convert this object into a `Future` which will resolve when a value is
@@ -308,8 +342,10 @@ impl<T> IntoFuture for FutureReader<T> {
308
342
reader : Some ( self ) ,
309
343
future : super :: with_entry ( handle, |entry| match entry {
310
344
Entry :: Vacant ( _) => unreachable ! ( ) ,
311
- Entry :: Occupied ( mut entry) => match entry. get ( ) {
312
- Handle :: Write | Handle :: LocalWaiting ( _) => unreachable ! ( ) ,
345
+ Entry :: Occupied ( mut entry) => match entry. get_mut ( ) {
346
+ Handle :: Write | Handle :: LocalWaiting ( _) => {
347
+ unreachable ! ( )
348
+ }
313
349
Handle :: Read => Box :: pin ( async move { ( vtable. read ) ( handle) . await } )
314
350
as Pin < Box < dyn Future < Output = _ > > > ,
315
351
Handle :: LocalOpen => {
@@ -318,6 +354,10 @@ impl<T> IntoFuture for FutureReader<T> {
318
354
Box :: pin ( async move { rx. await . ok ( ) . map ( |v| * v. downcast ( ) . unwrap ( ) ) } )
319
355
}
320
356
Handle :: LocalClosed => Box :: pin ( future:: ready ( None ) ) ,
357
+ Handle :: WriteClosedErr ( err_ctx) => match err_ctx. take ( ) {
358
+ None => Box :: pin ( future:: ready ( None ) ) ,
359
+ Some ( err_ctx) => Box :: pin ( future:: ready ( Some ( Err ( err_ctx) ) ) ) ,
360
+ } ,
321
361
Handle :: LocalReady ( ..) => {
322
362
let Handle :: LocalReady ( v, waker) = entry. insert ( Handle :: LocalClosed ) else {
323
363
unreachable ! ( )
@@ -353,7 +393,7 @@ impl<T> Drop for FutureReader<T> {
353
393
entry. remove ( ) ;
354
394
( self . vtable . close_readable ) ( handle) ;
355
395
}
356
- Handle :: Write => unreachable ! ( ) ,
396
+ Handle :: Write | Handle :: WriteClosedErr ( _ ) => unreachable ! ( ) ,
357
397
} ,
358
398
} ) ;
359
399
}
0 commit comments