@@ -27,8 +27,8 @@ pub(crate) struct TaskVTable {
27
27
/// Returns a pointer to the output stored after completion.
28
28
pub ( crate ) get_output : unsafe fn ( * const ( ) ) -> * const ( ) ,
29
29
30
- /// Drops a waker or a task.
31
- pub ( crate ) decrement : unsafe fn ( ptr : * const ( ) ) ,
30
+ /// Drops the task.
31
+ pub ( crate ) drop_task : unsafe fn ( ptr : * const ( ) ) ,
32
32
33
33
/// Destroys the task.
34
34
pub ( crate ) destroy : unsafe fn ( * const ( ) ) ,
@@ -39,7 +39,7 @@ pub(crate) struct TaskVTable {
39
39
40
40
/// Memory layout of a task.
41
41
///
42
- /// This struct contains the information on :
42
+ /// This struct contains the following information :
43
43
///
44
44
/// 1. How to allocate and deallocate the task.
45
45
/// 2. How to access the fields inside the task.
@@ -61,7 +61,7 @@ pub(crate) struct TaskLayout {
61
61
pub ( crate ) offset_r : usize ,
62
62
}
63
63
64
- /// Raw pointers to the fields of a task.
64
+ /// Raw pointers to the fields inside a task.
65
65
pub ( crate ) struct RawTask < F , R , S , T > {
66
66
/// The task header.
67
67
pub ( crate ) header : * const Header ,
@@ -102,7 +102,7 @@ where
102
102
{
103
103
/// Allocates a task with the given `future` and `schedule` function.
104
104
///
105
- /// It is assumed there are initially only the `Task` reference and the `JoinHandle`.
105
+ /// It is assumed that initially only the `Task` reference and the `JoinHandle` exist .
106
106
pub ( crate ) fn allocate ( tag : T , future : F , schedule : S ) -> NonNull < ( ) > {
107
107
// Compute the layout of the task for allocation. Abort if the computation fails.
108
108
let task_layout = abort_on_panic ( || Self :: task_layout ( ) ) ;
@@ -125,12 +125,12 @@ where
125
125
Self :: clone_waker,
126
126
Self :: wake,
127
127
Self :: wake_by_ref,
128
- Self :: decrement ,
128
+ Self :: drop_waker ,
129
129
) ,
130
130
schedule : Self :: schedule,
131
131
drop_future : Self :: drop_future,
132
132
get_output : Self :: get_output,
133
- decrement : Self :: decrement ,
133
+ drop_task : Self :: drop_task ,
134
134
destroy : Self :: destroy,
135
135
run : Self :: run,
136
136
} ,
@@ -181,7 +181,7 @@ where
181
181
let align_union = layout_f. align ( ) . max ( layout_r. align ( ) ) ;
182
182
let layout_union = unsafe { Layout :: from_size_align_unchecked ( size_union, align_union) } ;
183
183
184
- // Compute the layout for `Header` followed by `T`, then `S`, then `union { F, R }`.
184
+ // Compute the layout for `Header` followed by `T`, then `S`, and finally `union { F, R }`.
185
185
let layout = layout_header;
186
186
let ( layout, offset_t) = extend ( layout, layout_t) ;
187
187
let ( layout, offset_s) = extend ( layout, layout_s) ;
@@ -205,10 +205,10 @@ where
205
205
let mut state = ( * raw. header ) . state . load ( Ordering :: Acquire ) ;
206
206
207
207
loop {
208
- // If the task is completed or closed, it can't be woken.
208
+ // If the task is completed or closed, it can't be woken up .
209
209
if state & ( COMPLETED | CLOSED ) != 0 {
210
210
// Drop the waker.
211
- Self :: decrement ( ptr) ;
211
+ Self :: drop_waker ( ptr) ;
212
212
break ;
213
213
}
214
214
@@ -224,7 +224,7 @@ where
224
224
) {
225
225
Ok ( _) => {
226
226
// Drop the waker.
227
- Self :: decrement ( ptr) ;
227
+ Self :: drop_waker ( ptr) ;
228
228
break ;
229
229
}
230
230
Err ( s) => state = s,
@@ -249,7 +249,7 @@ where
249
249
( * raw. schedule ) ( task) ;
250
250
} else {
251
251
// Drop the waker.
252
- Self :: decrement ( ptr) ;
252
+ Self :: drop_waker ( ptr) ;
253
253
}
254
254
255
255
break ;
@@ -267,7 +267,7 @@ where
267
267
let mut state = ( * raw. header ) . state . load ( Ordering :: Acquire ) ;
268
268
269
269
loop {
270
- // If the task is completed or closed, it can't be woken.
270
+ // If the task is completed or closed, it can't be woken up .
271
271
if state & ( COMPLETED | CLOSED ) != 0 {
272
272
break ;
273
273
}
@@ -330,7 +330,7 @@ where
330
330
let raw_waker = & ( * raw. header ) . vtable . raw_waker ;
331
331
332
332
// Increment the reference count. With any kind of reference-counted data structure,
333
- // relaxed ordering is fine when the reference is being cloned .
333
+ // relaxed ordering is appropriate when incrementing the counter .
334
334
let state = ( * raw. header ) . state . fetch_add ( REFERENCE , Ordering :: Relaxed ) ;
335
335
336
336
// If the reference count overflowed, abort.
@@ -341,19 +341,48 @@ where
341
341
RawWaker :: new ( ptr, raw_waker)
342
342
}
343
343
344
- /// Drops a waker or a task.
344
+ /// Drops a waker.
345
+ ///
346
+ /// This function will decrement the reference count. If it drops down to zero, the associated
347
+ /// join handle has been dropped too, and the task has not been completed, then it will get
348
+ /// scheduled one more time so that its future gets dropped by the executor.
349
+ #[ inline]
350
+ unsafe fn drop_waker ( ptr : * const ( ) ) {
351
+ let raw = Self :: from_ptr ( ptr) ;
352
+
353
+ // Decrement the reference count.
354
+ let new = ( * raw. header ) . state . fetch_sub ( REFERENCE , Ordering :: AcqRel ) - REFERENCE ;
355
+
356
+ // If this was the last reference to the task and the `JoinHandle` has been dropped too,
357
+ // then we need to decide how to destroy the task.
358
+ if new & !( REFERENCE - 1 ) == 0 && new & HANDLE == 0 {
359
+ if new & ( COMPLETED | CLOSED ) == 0 {
360
+ // If the task was not completed nor closed, close it and schedule one more time so
361
+ // that its future gets dropped by the executor.
362
+ ( * raw. header )
363
+ . state
364
+ . store ( SCHEDULED | CLOSED | REFERENCE , Ordering :: Release ) ;
365
+ ( ( * raw. header ) . vtable . schedule ) ( ptr) ;
366
+ } else {
367
+ // Otherwise, destroy the task right away.
368
+ Self :: destroy ( ptr) ;
369
+ }
370
+ }
371
+ }
372
+
373
+ /// Drops a task.
345
374
///
346
375
/// This function will decrement the reference count. If it drops down to zero and the
347
376
/// associated join handle has been dropped too, then the task gets destroyed.
348
377
#[ inline]
349
- unsafe fn decrement ( ptr : * const ( ) ) {
378
+ unsafe fn drop_task ( ptr : * const ( ) ) {
350
379
let raw = Self :: from_ptr ( ptr) ;
351
380
352
381
// Decrement the reference count.
353
382
let new = ( * raw. header ) . state . fetch_sub ( REFERENCE , Ordering :: AcqRel ) - REFERENCE ;
354
383
355
- // If this was the last reference to the task and the `JoinHandle` has been dropped as
356
- // well, then destroy the task.
384
+ // If this was the last reference to the task and the `JoinHandle` has been dropped too,
385
+ // then destroy the task.
357
386
if new & !( REFERENCE - 1 ) == 0 && new & HANDLE == 0 {
358
387
Self :: destroy ( ptr) ;
359
388
}
@@ -391,8 +420,8 @@ where
391
420
392
421
/// Cleans up task's resources and deallocates it.
393
422
///
394
- /// If the task has not been closed, then its future or the output will be dropped. The
395
- /// schedule function and the tag get dropped too .
423
+ /// The schedule function and the tag will be dropped, and the task will then get deallocated.
424
+ /// The task must be closed before this function is called .
396
425
#[ inline]
397
426
unsafe fn destroy ( ptr : * const ( ) ) {
398
427
let raw = Self :: from_ptr ( ptr) ;
@@ -413,8 +442,8 @@ where
413
442
414
443
/// Runs a task.
415
444
///
416
- /// If polling its future panics, the task will be closed and the panic propagated into the
417
- /// caller.
445
+ /// If polling its future panics, the task will be closed and the panic will be propagated into
446
+ /// the caller.
418
447
unsafe fn run ( ptr : * const ( ) ) {
419
448
let raw = Self :: from_ptr ( ptr) ;
420
449
@@ -429,7 +458,7 @@ where
429
458
430
459
// Update the task's state before polling its future.
431
460
loop {
432
- // If the task has been closed, drop the task reference and return.
461
+ // If the task has already been closed, drop the task reference and return.
433
462
if state & CLOSED != 0 {
434
463
// Notify the awaiter that the task has been closed.
435
464
if state & AWAITER != 0 {
@@ -440,7 +469,7 @@ where
440
469
Self :: drop_future ( ptr) ;
441
470
442
471
// Drop the task reference.
443
- Self :: decrement ( ptr) ;
472
+ Self :: drop_task ( ptr) ;
444
473
return ;
445
474
}
446
475
@@ -505,7 +534,7 @@ where
505
534
}
506
535
507
536
// Drop the task reference.
508
- Self :: decrement ( ptr) ;
537
+ Self :: drop_task ( ptr) ;
509
538
break ;
510
539
}
511
540
Err ( s) => state = s,
@@ -519,7 +548,7 @@ where
519
548
// The task is still not completed.
520
549
loop {
521
550
// If the task was closed while running, we'll need to unschedule in case it
522
- // was woken and then clean up its resources .
551
+ // was woken up and then destroy it .
523
552
let new = if state & CLOSED != 0 {
524
553
state & !RUNNING & !SCHEDULED
525
554
} else {
@@ -535,22 +564,22 @@ where
535
564
) {
536
565
Ok ( state) => {
537
566
// If the task was closed while running, we need to drop its future.
538
- // If the task was woken while running, we need to schedule it.
567
+ // If the task was woken up while running, we need to schedule it.
539
568
// Otherwise, we just drop the task reference.
540
569
if state & CLOSED != 0 {
541
570
// The thread that closed the task didn't drop the future because
542
571
// it was running so now it's our responsibility to do so.
543
572
Self :: drop_future ( ptr) ;
544
573
545
574
// Drop the task reference.
546
- Self :: decrement ( ptr) ;
575
+ Self :: drop_task ( ptr) ;
547
576
} else if state & SCHEDULED != 0 {
548
- // The thread that has woken the task didn't reschedule it because
577
+ // The thread that woke the task up didn't reschedule it because
549
578
// it was running so now it's our responsibility to do so.
550
579
Self :: schedule ( ptr) ;
551
580
} else {
552
581
// Drop the task reference.
553
- Self :: decrement ( ptr) ;
582
+ Self :: drop_task ( ptr) ;
554
583
}
555
584
break ;
556
585
}
@@ -587,15 +616,15 @@ where
587
616
// future, and drop the task reference.
588
617
if state & CLOSED != 0 {
589
618
// We still need to unschedule the task because it is possible it was
590
- // woken while running.
619
+ // woken up while running.
591
620
( * raw. header ) . state . fetch_and ( !SCHEDULED , Ordering :: AcqRel ) ;
592
621
593
622
// The thread that closed the task didn't drop the future because it
594
623
// was running so now it's our responsibility to do so.
595
624
RawTask :: < F , R , S , T > :: drop_future ( ptr) ;
596
625
597
626
// Drop the task reference.
598
- RawTask :: < F , R , S , T > :: decrement ( ptr) ;
627
+ RawTask :: < F , R , S , T > :: drop_task ( ptr) ;
599
628
break ;
600
629
}
601
630
@@ -616,7 +645,7 @@ where
616
645
}
617
646
618
647
// Drop the task reference.
619
- RawTask :: < F , R , S , T > :: decrement ( ptr) ;
648
+ RawTask :: < F , R , S , T > :: drop_task ( ptr) ;
620
649
break ;
621
650
}
622
651
Err ( s) => state = s,
0 commit comments