@@ -287,11 +287,9 @@ class alignas(2 * sizeof(void*)) ActiveTaskStatus {
287
287
// / or is completed.
288
288
IsEnqueued = 0x1000 ,
289
289
290
- #ifndef NDEBUG
291
290
// / Task has been completed. This is purely used to enable an assertion
292
291
// / that the task is completed when we destroy it.
293
292
IsComplete = 0x2000 ,
294
- #endif
295
293
};
296
294
297
295
// Note: this structure is mirrored by ActiveTaskStatusWithEscalation and
@@ -409,7 +407,6 @@ class alignas(2 * sizeof(void*)) ActiveTaskStatus {
409
407
#endif
410
408
}
411
409
412
- #ifndef NDEBUG
413
410
bool isComplete () const {
414
411
return Flags & IsComplete;
415
412
}
@@ -421,7 +418,6 @@ class alignas(2 * sizeof(void*)) ActiveTaskStatus {
421
418
return ActiveTaskStatus (Record, Flags | IsComplete);
422
419
#endif
423
420
}
424
- #endif
425
421
426
422
// / Is there a lock on the linked list of status records?
427
423
bool isStatusRecordLocked () const { return Flags & IsStatusRecordLocked; }
@@ -596,9 +592,7 @@ struct AsyncTask::PrivateStorage {
596
592
auto newStatus = oldStatus.withRunning (false );
597
593
newStatus = newStatus.withoutStoredPriorityEscalation ();
598
594
newStatus = newStatus.withoutEnqueued ();
599
- #ifndef NDEBUG
600
595
newStatus = newStatus.withComplete ();
601
- #endif
602
596
603
597
// This can fail since the task can still get concurrently cancelled or
604
598
// escalated.
@@ -615,10 +609,22 @@ struct AsyncTask::PrivateStorage {
615
609
}
616
610
}
617
611
618
- // Destroy and deallocate any remaining task local items.
619
- // We need to do this before we destroy the task local deallocator.
612
+ // Destroy and deallocate any remaining task local items since the task is
613
+ // completed. We need to do this before we destroy the task local
614
+ // deallocator.
620
615
Local.destroy (task);
621
616
617
+ // Don't destroy the task private storage as a whole since others which have
618
+ // a reference to the task might still need to access the ActiveTaskStatus.
619
+ // It is destroyed when task is destroyed
620
+ }
621
+
622
+ // Destroy the opaque storage of the task
623
+ void destroy () {
624
+ #if NDEBUG
625
+ auto oldStatus = task->_private ()._status ().load (std::memory_order_relaxed);
626
+ assert (oldStatus.isComplete ());
627
+ #endif
622
628
this ->~PrivateStorage ();
623
629
}
624
630
@@ -653,11 +659,13 @@ inline void AsyncTask::OpaquePrivateStorage::initializeWithSlab(
653
659
JobPriority basePri, void *slab, size_t slabCapacity) {
654
660
::new (this ) PrivateStorage (basePri, slab, slabCapacity);
655
661
}
662
+
656
663
inline void AsyncTask::OpaquePrivateStorage::complete (AsyncTask *task) {
657
664
get ().complete (task);
658
665
}
666
+
659
667
inline void AsyncTask::OpaquePrivateStorage::destroy () {
660
- // nothing else to do
668
+ get (). destroy ();
661
669
}
662
670
663
671
inline AsyncTask::PrivateStorage &AsyncTask::_private () {
@@ -822,10 +830,10 @@ inline void AsyncTask::flagAsSuspended() {
822
830
}
823
831
824
832
// READ ME: This is not a dead function! Do not remove it! This is a function
825
- // that can be used when debugging locally to instrument when a task actually is
826
- // dealloced.
827
- inline void AsyncTask::flagAsCompleted () {
828
- SWIFT_TASK_DEBUG_LOG (" task completed %p" , this );
833
+ // that can be used when debugging locally to instrument when a task
834
+ // actually is dealloced.
835
+ inline void AsyncTask::flagAsDestroyed () {
836
+ SWIFT_TASK_DEBUG_LOG (" task destroyed %p" , this );
829
837
}
830
838
831
839
inline void AsyncTask::localValuePush (const HeapObject *key,
0 commit comments