@@ -114,7 +114,7 @@ class NaiveTaskGroupQueue {
114
114
queue = std::move (other.queue );
115
115
}
116
116
117
- virtual ~NaiveTaskGroupQueue () {}
117
+ ~NaiveTaskGroupQueue () {}
118
118
119
119
bool dequeue (T &output) {
120
120
if (queue.empty ()) {
@@ -1035,7 +1035,7 @@ static void _enqueueRawError(DiscardingTaskGroup* _Nonnull group,
1035
1035
// TaskGroup is locked upon entry and exit
1036
1036
void AccumulatingTaskGroup::enqueueCompletedTask (AsyncTask *completedTask, bool hadErrorResult) {
1037
1037
// Retain the task while it is in the queue; it must remain alive until
1038
- // it is found by poll. This retain will balanced by the release in poll.
1038
+ // it is found by poll. This retain will be balanced by the release in poll.
1039
1039
swift_retain (completedTask);
1040
1040
1041
1041
_enqueueCompletedTask (&readyQueue, completedTask, hadErrorResult);
@@ -1181,9 +1181,11 @@ void DiscardingTaskGroup::offer(AsyncTask *completedTask, AsyncContext *context)
1181
1181
if (readyQueue.dequeue (readyErrorItem)) {
1182
1182
switch (readyErrorItem.getStatus ()) {
1183
1183
case ReadyStatus::RawError:
1184
+ SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, resume with raw error:%p" , readyErrorItem.getRawError (this ));
1184
1185
resumeWaitingTaskWithError (readyErrorItem.getRawError (this ), assumed, alreadyDecrementedStatus);
1185
1186
break ;
1186
1187
case ReadyStatus::Error:
1188
+ SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, resume with errorItem.task:%p" , readyErrorItem.getTask ());
1187
1189
resumeWaitingTask (readyErrorItem.getTask (), assumed, /* hadErrorResult=*/ true , alreadyDecrementedStatus);
1188
1190
break ;
1189
1191
default :
@@ -1197,16 +1199,18 @@ void DiscardingTaskGroup::offer(AsyncTask *completedTask, AsyncContext *context)
1197
1199
} else if (readyQueue.isEmpty ()) {
1198
1200
// There was no waiting task, or other tasks are still pending, so we cannot
1199
1201
// it is the first error we encountered, thus we need to store it for future throwing
1202
+ SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, enqueue child task:%p" , completedTask);
1200
1203
enqueueCompletedTask (completedTask, hadErrorResult);
1201
1204
} else {
1205
+ SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, discard child task:%p" , completedTask);
1202
1206
_swift_taskGroup_detachChild (asAbstract (this ), completedTask);
1203
1207
}
1204
1208
1205
1209
unlock ();
1206
1210
return ;
1207
1211
}
1208
1212
1209
- assert (!hadErrorResult);
1213
+ assert (!hadErrorResult && " only successfully completed tasks can reach here " );
1210
1214
if (afterComplete.hasWaitingTask () && afterComplete.pendingTasks (this ) == 0 ) {
1211
1215
SWIFT_TASK_GROUP_DEBUG_LOG (this ,
1212
1216
" offer, last pending task completed successfully, resume waitingTask with completedTask:%p" ,
@@ -1295,6 +1299,12 @@ void TaskGroupBase::resumeWaitingTask(
1295
1299
" resume waiting DONE, task = %p, backup = %p, complete with = %p, status = %s" ,
1296
1300
waitingTask, backup, completedTask, statusString ().c_str ());
1297
1301
1302
+ auto waitingContext =
1303
+ static_cast <TaskFutureWaitAsyncContext *>(
1304
+ waitingTask->ResumeContext );
1305
+
1306
+ fillGroupNextResult (waitingContext, result);
1307
+
1298
1308
// Remove the child from the task group's running tasks list.
1299
1309
// The parent task isn't currently running (we're about to wake
1300
1310
// it up), so we're still synchronous with it. We can safely
@@ -1305,12 +1315,6 @@ void TaskGroupBase::resumeWaitingTask(
1305
1315
// we can't be holding its locks ourselves.
1306
1316
_swift_taskGroup_detachChild (asAbstract (this ), completedTask);
1307
1317
1308
- auto waitingContext =
1309
- static_cast <TaskFutureWaitAsyncContext *>(
1310
- waitingTask->ResumeContext );
1311
-
1312
- fillGroupNextResult (waitingContext, result);
1313
-
1314
1318
_swift_tsan_acquire (static_cast <Job *>(waitingTask));
1315
1319
// TODO: allow the caller to suggest an executor
1316
1320
waitingTask->flagAsAndEnqueueOnExecutor (ExecutorRef::generic ());
@@ -1660,8 +1664,8 @@ static void swift_taskGroup_waitAllImpl(
1660
1664
context->errorResult = nullptr ;
1661
1665
context->successResultPointer = resultPointer;
1662
1666
1663
- SWIFT_TASK_GROUP_DEBUG_LOG (group, " waitAllImpl, waiting task = %p, bodyError = %p, status:%s, polled.status = %s, status.NOW=%s" ,
1664
- waitingTask, bodyError, group->statusString ().c_str (), to_string (polled.status ).c_str (), group->statusString ().c_str ());
1667
+ // SWIFT_TASK_GROUP_DEBUG_LOG(group, "waitAllImpl, waiting task = %p, bodyError = %p, status:%s, polled.status = %s, status.NOW=%s",
1668
+ // waitingTask, bodyError, group->statusString().c_str(), to_string(polled.status).c_str(), group->statusString().c_str());
1665
1669
1666
1670
switch (polled.status ) {
1667
1671
case PollStatus::MustWait: {
@@ -1789,16 +1793,13 @@ PollResult TaskGroupBase::waitAll(SwiftError* bodyError, AsyncTask *waitingTask,
1789
1793
waitingTask->flagAsSuspended ();
1790
1794
}
1791
1795
// Put the waiting task at the beginning of the wait queue.
1792
- SWIFT_TASK_GROUP_DEBUG_LOG (this , " WATCH OUT, set waiter onto... waitQueue.head = %p" , waitQueue.load (std::memory_order_relaxed));
1793
-
1794
1796
if (waitQueue.compare_exchange_strong (
1795
1797
waitHead, waitingTask,
1796
1798
/* success*/ std::memory_order_release,
1797
1799
/* failure*/ std::memory_order_acquire)) {
1798
1800
statusMarkWaitingAssumeRelease ();
1799
1801
SWIFT_TASK_GROUP_DEBUG_LOG (this , " waitAll, marked waiting status = %s" , statusString ().c_str ());
1800
- unlock ();
1801
-
1802
+
1802
1803
#if SWIFT_CONCURRENCY_TASK_TO_THREAD_MODEL
1803
1804
// The logic here is paired with the logic in TaskGroupBase::offer. Once
1804
1805
// we run the
@@ -1824,6 +1825,8 @@ PollResult TaskGroupBase::waitAll(SwiftError* bodyError, AsyncTask *waitingTask,
1824
1825
// no ready tasks, so we must wait.
1825
1826
result.status = PollStatus::MustWait;
1826
1827
_swift_task_clearCurrent ();
1828
+
1829
+ unlock ();
1827
1830
return result;
1828
1831
} // else, try again
1829
1832
}
0 commit comments