@@ -114,12 +114,6 @@ class TaskGroupImpl: public TaskGroupTaskStatusRecord {
114
114
// / until a next() call eventually picks it up.
115
115
AsyncTask *retainedTask;
116
116
117
- bool isStorageAccessible () {
118
- return status == PollStatus::Success ||
119
- status == PollStatus::Error ||
120
- status == PollStatus::Empty;
121
- }
122
-
123
117
static PollResult get (AsyncTask *asyncTask, bool hadErrorResult) {
124
118
auto fragment = asyncTask->futureFragment ();
125
119
return PollResult{
@@ -134,11 +128,11 @@ class TaskGroupImpl: public TaskGroupTaskStatusRecord {
134
128
};
135
129
}
136
130
137
- static PollResult getVoid ( ) {
131
+ static PollResult getEmpty ( const Metadata *successType ) {
138
132
return PollResult{
139
133
/* status*/ PollStatus::Success,
140
134
/* storage*/ nullptr ,
141
- /* successType*/ nullptr , // TODO: Void.self
135
+ /* successType*/ successType,
142
136
/* task*/ nullptr
143
137
};
144
138
}
@@ -435,6 +429,17 @@ class TaskGroupImpl: public TaskGroupTaskStatusRecord {
435
429
// / or a `PollStatus::MustWait` result if there are tasks in flight
436
430
// / and the waitingTask eventually be woken up by a completion.
437
431
PollResult poll (AsyncTask *waitingTask);
432
+
433
+ // / A `discardResults` TaskGroup is not able to wait on individual completions,
434
+ // / instead, it can only await on "all pending tasks have been processed".
435
+ // /
436
+ // /
437
+ // / If unable to complete the waiting task immediately (with an readily
438
+ // / available completed task), either returns an `PollStatus::Empty`
439
+ // / result if it is known that no pending tasks in the group,
440
+ // / or a `PollStatus::MustWait` result if there are tasks in flight
441
+ // / and the waitingTask eventually be woken up by a completion.
442
+ PollResult waitAll (AsyncTask *waitingTask);
438
443
};
439
444
440
445
} // end anonymous namespace
@@ -593,7 +598,7 @@ void TaskGroupImpl::offer(AsyncTask *completedTask, AsyncContext *context) {
593
598
// W:n R:0 P:1 -> W:y R:1 P:1 // complete immediately
594
599
// W:n R:0 P:1 -> W:y R:1 P:3 // complete immediately, 2 more pending tasks
595
600
auto assumed = statusAddReadyAssumeAcquire ();
596
- SWIFT_TASK_DEBUG_LOG (" offer task %p to group %p , tasks pending = %d" , completedTask, assumed.pendingTasks ());
601
+ SWIFT_TASK_DEBUG_LOG (" offer task %p to group(%p) , tasks pending = %d" , completedTask, assumed.pendingTasks ());
597
602
598
603
auto asyncContextPrefix = reinterpret_cast <FutureAsyncContextPrefix *>(
599
604
reinterpret_cast <char *>(context) - sizeof (FutureAsyncContextPrefix));
@@ -629,13 +634,7 @@ void TaskGroupImpl::offer(AsyncTask *completedTask, AsyncContext *context) {
629
634
static_cast <TaskFutureWaitAsyncContext *>(
630
635
waitingTask->ResumeContext );
631
636
632
- if (isDiscardingResults ()) {
633
- fprintf (stderr, " [%s:%d](%s) offer: discardResults\n " , __FILE_NAME__, __LINE__, __FUNCTION__);
634
- fillGroupNextResult (waitingContext, result);
635
- } else {
636
- fprintf (stderr, " [%s:%d](%s) offer: NOT\n " , __FILE_NAME__, __LINE__, __FUNCTION__);
637
- fillGroupNextResult (waitingContext, result);
638
- }
637
+ fillGroupNextResult (waitingContext, result);
639
638
detachChild (result.retainedTask );
640
639
641
640
_swift_tsan_acquire (static_cast <Job *>(waitingTask));
@@ -655,29 +654,20 @@ void TaskGroupImpl::offer(AsyncTask *completedTask, AsyncContext *context) {
655
654
// queue when a task polls during next() it will notice that we have a value
656
655
// ready for it, and will process it immediately without suspending.
657
656
assert (!waitQueue.load (std::memory_order_relaxed));
658
- if (isDiscardingResults ()) {
659
- // DO NOT retain the task; and do not store the value in the readyQueue at all (!)
660
- //
661
- // In the "eagerlyRelease" completed tasks mode, we are guaranteed that tasks are of Void type,
662
- // and thus there is no necessity to store values, because we can always "make them up" when polled.
663
- // From the user's perspective, it is indistinguishable if they received the "real value" or one we "made up",
664
- // because Void is always the same, and cannot be examined in any way to determine if it was the "actual" Void or not.
665
- } else {
666
- SWIFT_TASK_DEBUG_LOG (" group has no waiting tasks, RETAIN and store ready task = %p" ,
667
- completedTask);
668
- // Retain the task while it is in the queue;
669
- // it must remain alive until the task group is alive.
670
- swift_retain (completedTask);
671
-
672
- auto readyItem = ReadyQueueItem::get (
673
- hadErrorResult ? ReadyStatus::Error : ReadyStatus::Success,
674
- completedTask
675
- );
676
-
677
- assert (completedTask == readyItem.getTask ());
678
- assert (readyItem.getTask ()->isFuture ());
679
- readyQueue.enqueue (readyItem);
680
- }
657
+ SWIFT_TASK_DEBUG_LOG (" group has no waiting tasks, RETAIN and store ready task = %p" ,
658
+ completedTask);
659
+ // Retain the task while it is in the queue;
660
+ // it must remain alive until the task group is alive.
661
+ swift_retain (completedTask);
662
+
663
+ auto readyItem = ReadyQueueItem::get (
664
+ hadErrorResult ? ReadyStatus::Error : ReadyStatus::Success,
665
+ completedTask
666
+ );
667
+
668
+ assert (completedTask == readyItem.getTask ());
669
+ assert (readyItem.getTask ()->isFuture ());
670
+ readyQueue.enqueue (readyItem);
681
671
682
672
mutex.unlock (); // TODO: remove fragment lock, and use status for synchronization
683
673
return ;
@@ -713,16 +703,6 @@ SWIFT_CC(swiftasync) static void workaround_function_swift_taskGroup_wait_next_t
713
703
// =============================================================================
714
704
// ==== group.next() implementation (wait_next and groupPoll) ------------------
715
705
716
- SWIFT_CC (swiftasync)
717
- static void swift_taskGroup_wait_next_discardResultsImpl(
718
- OpaqueValue *resultPointer, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
719
- TaskGroupImpl *group,
720
- ThrowingTaskFutureWaitContinuationFunction *resumeFunction,
721
- AsyncContext *rawContext,
722
- AsyncTask *waitingTask) {
723
-
724
- }
725
-
726
706
SWIFT_CC (swiftasync)
727
707
static void swift_taskGroup_wait_next_throwingImpl(
728
708
OpaqueValue *resultPointer, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
@@ -736,11 +716,6 @@ static void swift_taskGroup_wait_next_throwingImpl(
736
716
auto group = asImpl (_group);
737
717
assert (group && " swift_taskGroup_wait_next_throwing was passed context without group!" );
738
718
739
- if (group->discardResults ) {
740
- return swift_taskGroup_wait_next_discardResultsImpl (
741
- callerContext, group, resumeFunction, rawContext, waitingTask)
742
- }
743
-
744
719
auto context = static_cast <TaskFutureWaitAsyncContext *>(rawContext);
745
720
context->ResumeParent =
746
721
reinterpret_cast <TaskContinuationFunction *>(resumeFunction);
@@ -767,11 +742,7 @@ static void swift_taskGroup_wait_next_throwingImpl(
767
742
case PollStatus::Success:
768
743
SWIFT_TASK_DEBUG_LOG (" poll group = %p, task = %p, ready task available = %p" ,
769
744
group, waitingTask, polled.retainedTask );
770
- if (isDiscardingResults ()) {
771
- fillGroupNextNilResult (context);
772
- } else {
773
- fillGroupNextResult (context, polled);
774
- }
745
+ fillGroupNextResult (context, polled);
775
746
776
747
if (auto completedTask = polled.retainedTask ) {
777
748
// it would be null for PollStatus::Empty, then we don't need to release
@@ -818,7 +789,7 @@ PollResult TaskGroupImpl::poll(AsyncTask *waitingTask) {
818
789
auto assumedStatus = assumed.status ;
819
790
auto newStatus = TaskGroupImpl::GroupStatus{assumedStatus};
820
791
if (status.compare_exchange_strong (
821
- assumedStatus, newStatus.completingPendingReadyWaiting ().status ,
792
+ assumedStatus, newStatus.completingPendingReadyWaiting (this ).status ,
822
793
/* success*/ std::memory_order_relaxed,
823
794
/* failure*/ std::memory_order_acquire)) {
824
795
@@ -897,14 +868,13 @@ PollResult TaskGroupImpl::poll(AsyncTask *waitingTask) {
897
868
}
898
869
899
870
// =============================================================================
900
- // ==== isEmpty ----------------------------------------------------------------
871
+ // ==== Task Group status and flag checks -------------------------------------
872
+
901
873
SWIFT_CC (swift)
902
874
static bool swift_taskGroup_isEmptyImpl(TaskGroup *group) {
903
875
return asImpl (group)->isEmpty ();
904
876
}
905
877
906
- // =============================================================================
907
- // ==== isCancelled ------------------------------------------------------------
908
878
SWIFT_CC (swift)
909
879
static bool swift_taskGroup_isCancelledImpl(TaskGroup *group) {
910
880
return asImpl (group)->isCancelled ();
0 commit comments