6464
6565using namespace swift ;
6666
67- #if 1
67+ #if 0
6868#define SWIFT_TASK_GROUP_DEBUG_LOG(group, fmt, ...) \
6969fprintf(stderr, "[%#lx] [%s:%d][group(%p%s)] (%s) " fmt "\n", \
7070 (unsigned long)Thread::current().platformThreadId(), \
@@ -390,7 +390,11 @@ class TaskGroupBase : public TaskGroupTaskStatusRecord {
390390 virtual void enqueueCompletedTask (AsyncTask *completedTask, bool hadErrorResult) = 0;
391391
392392 // / Resume waiting task with result from `completedTask`
393- void resumeWaitingTask (AsyncTask *completedTask, TaskGroupStatus &assumed, bool hadErrorResult, bool alreadyDecremented = false );
393+ void resumeWaitingTask (AsyncTask *completedTask,
394+ TaskGroupStatus &assumed,
395+ bool hadErrorResult,
396+ bool alreadyDecremented = false ,
397+ bool taskWasRetained = false );
394398
395399 // ==== Status manipulation -------------------------------------------------
396400
@@ -827,7 +831,9 @@ class DiscardingTaskGroup: public TaskGroupBase {
827831
828832private:
829833 // / Resume waiting task with specified error
830- void resumeWaitingTaskWithError (SwiftError *error, TaskGroupStatus &assumed, bool alreadyDecremented);
834+ void resumeWaitingTaskWithError (SwiftError *error,
835+ TaskGroupStatus &assumed,
836+ bool alreadyDecremented);
831837};
832838
833839} // end anonymous namespace
@@ -1040,7 +1046,7 @@ static void fillGroupNextResult(TaskFutureWaitAsyncContext *context,
10401046
10411047 case PollStatus::Error: {
10421048 auto error = reinterpret_cast <SwiftError *>(result.storage );
1043- fillGroupNextErrorResult (context, error); // FIXME: this specifically retains the error, but likely should not!??!!?
1049+ fillGroupNextErrorResult (context, error);
10441050 return ;
10451051 }
10461052
@@ -1240,11 +1246,16 @@ void DiscardingTaskGroup::offer(AsyncTask *completedTask, AsyncContext *context)
12401246 switch (readyErrorItem.getStatus ()) {
12411247 case ReadyStatus::RawError:
12421248 SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, resume with raw error:%p" , readyErrorItem.getRawError (this ));
1243- resumeWaitingTaskWithError (readyErrorItem.getRawError (this ), assumed, alreadyDecrementedStatus);
1249+ resumeWaitingTaskWithError (readyErrorItem.getRawError (this ), assumed,
1250+ alreadyDecrementedStatus);
12441251 break ;
12451252 case ReadyStatus::Error:
12461253 SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, resume with errorItem.task:%p" , readyErrorItem.getTask ());
1247- resumeWaitingTask (readyErrorItem.getTask (), assumed, /* hadErrorResult=*/ true , alreadyDecrementedStatus);
1254+ SWIFT_TASK_GROUP_DEBUG_LOG (this , " offer, complete, expect that it was extra retained %p" , readyErrorItem.getTask ());
1255+ resumeWaitingTask (readyErrorItem.getTask (), assumed,
1256+ /* hadErrorResult=*/ true ,
1257+ alreadyDecrementedStatus,
1258+ /* taskWasRetained=*/ true );
12481259 break ;
12491260 default :
12501261 swift_Concurrency_fatalError (0 ,
@@ -1283,7 +1294,10 @@ void DiscardingTaskGroup::offer(AsyncTask *completedTask, AsyncContext *context)
12831294 resumeWaitingTaskWithError (readyErrorItem.getRawError (this ), assumed, alreadyDecrementedStatus);
12841295 break ;
12851296 case ReadyStatus::Error:
1286- resumeWaitingTask (readyErrorItem.getTask (), assumed, /* hadErrorResult=*/ true , alreadyDecrementedStatus);
1297+ resumeWaitingTask (readyErrorItem.getTask (), assumed,
1298+ /* hadErrorResult=*/ true ,
1299+ alreadyDecrementedStatus,
1300+ /* taskWasRetained=*/ true );
12871301 break ;
12881302 default :
12891303 swift_Concurrency_fatalError (0 ,
@@ -1293,14 +1307,6 @@ void DiscardingTaskGroup::offer(AsyncTask *completedTask, AsyncContext *context)
12931307 // This is the last task, we have a waiting task and there was no error stored previously;
12941308 // We must resume the waiting task with a success, so let us return here.
12951309 resumeWaitingTask (completedTask, assumed, /* hadErrorResult=*/ false , alreadyDecrementedStatus);
1296-
1297- // // TODO: since the DiscardingTaskGroup ended up written as `-> T` in order to use the same pointer auth as the
1298- // // usual task closures; we end up retaining the value when it is returned. As this is a discarding group
1299- // // we actually can and should release this value.
1300- // // Is there a way we could avoid the retain made on the returned value entirely?
1301- // if (completedTask->futureFragment()->getResultType()->isClassObject()) {
1302- // swift_release(reinterpret_cast<HeapObject *>(completedTask->futureFragment()->getStoragePtr()));
1303- // }
13041310 }
13051311 } else {
13061312 // it wasn't the last pending task, and there is no-one to resume;
@@ -1317,7 +1323,8 @@ void TaskGroupBase::resumeWaitingTask(
13171323 AsyncTask *completedTask,
13181324 TaskGroupStatus &assumed,
13191325 bool hadErrorResult,
1320- bool alreadyDecremented) {
1326+ bool alreadyDecremented,
1327+ bool taskWasRetained) {
13211328 auto waitingTask = waitQueue.load (std::memory_order_acquire);
13221329 assert (waitingTask && " waitingTask must not be null when attempting to resume it" );
13231330 assert (assumed.hasWaitingTask ());
@@ -1384,14 +1391,14 @@ void TaskGroupBase::resumeWaitingTask(
13841391 auto before = completedTask;
13851392 _swift_taskGroup_detachChild (asAbstract (this ), completedTask);
13861393 SWIFT_TASK_GROUP_DEBUG_LOG (this , " completedTask %p; AFTER DETACH (count:%d)" , completedTask, swift_retainCount (completedTask));
1387- if (hadErrorResult) {
1394+ if (isDiscardingResults () && hadErrorResult && taskWasRetained ) {
13881395 SWIFT_TASK_GROUP_DEBUG_LOG (this , " BEFORE RELEASE error task=%p (count:%d)\n " ,
13891396 completedTask,
13901397 swift_retainCount (completedTask));
13911398 // We only used the task to keep the error in the future fragment around
13921399 // so now that we emitted the error and detached the task, we are free to release the task immediately.
1393- auto error = reinterpret_cast <SwiftError *>(result. storage );
1394- swift_release (completedTask); // we need to do this if the error is a class
1400+ auto error = completedTask-> futureFragment ()-> getError ( );
1401+ swift_release (completedTask);
13951402 }
13961403
13971404 _swift_tsan_acquire (static_cast <Job *>(waitingTask));
0 commit comments