@@ -197,9 +197,18 @@ impl Proactor {
197
197
/// but just don't return from [`Proactor::poll`]. Therefore, although an
198
198
/// operation is cancelled, you should not reuse its `user_data`.
199
199
///
200
- /// It is well-defined to cancel before polling. If the submitted operation
200
+ /// It is *safe* to cancel before polling. If the submitted operation
201
201
/// contains a cancelled user-defined data, the operation will be ignored.
202
+ /// However, to make the operation dropped correctly, you should cancel
203
+ /// after push.
202
204
pub fn cancel ( & mut self , user_data : usize ) {
205
+ if let Some ( op) = self . ops . get_mut ( user_data) {
206
+ if op. set_cancelled ( ) {
207
+ // The op is completed.
208
+ self . ops . remove ( user_data) ;
209
+ return ;
210
+ }
211
+ }
203
212
self . driver . cancel ( user_data, & mut self . ops ) ;
204
213
}
205
214
@@ -227,7 +236,8 @@ impl Proactor {
227
236
entries : & mut impl Extend < Entry > ,
228
237
) -> io:: Result < ( ) > {
229
238
unsafe {
230
- self . driver . poll ( timeout, entries, & mut self . ops ) ?;
239
+ self . driver
240
+ . poll ( timeout, OutEntries :: new ( entries, & mut self . ops ) ) ?;
231
241
}
232
242
Ok ( ( ) )
233
243
}
@@ -320,6 +330,35 @@ impl Entry {
320
330
}
321
331
}
322
332
333
+ // The output entries need to be marked as `completed`. If an entry has been
334
+ // marked as `cancelled`, it will be removed from the registry.
335
+ struct OutEntries < ' a , ' b , E > {
336
+ entries : & ' b mut E ,
337
+ registry : & ' a mut Slab < RawOp > ,
338
+ }
339
+
340
+ impl < ' a , ' b , E > OutEntries < ' a , ' b , E > {
341
+ pub fn new ( entries : & ' b mut E , registry : & ' a mut Slab < RawOp > ) -> Self {
342
+ Self { entries, registry }
343
+ }
344
+
345
+ #[ allow( dead_code) ]
346
+ pub fn registry ( & mut self ) -> & mut Slab < RawOp > {
347
+ self . registry
348
+ }
349
+ }
350
+
351
+ impl < E : Extend < Entry > > Extend < Entry > for OutEntries < ' _ , ' _ , E > {
352
+ fn extend < T : IntoIterator < Item = Entry > > ( & mut self , iter : T ) {
353
+ self . entries . extend ( iter. into_iter ( ) . map ( |e| {
354
+ if self . registry [ e. user_data ( ) ] . set_completed ( ) {
355
+ self . registry . remove ( e. user_data ( ) ) ;
356
+ }
357
+ e
358
+ } ) )
359
+ }
360
+ }
361
+
323
362
#[ derive( Debug , Clone ) ]
324
363
enum ThreadPoolBuilder {
325
364
Create { limit : usize , recv_limit : Duration } ,
0 commit comments