@@ -104,10 +104,13 @@ class TaskGroupBase : public TaskGroupTaskStatusRecord {
104
104
// / to that task or null.
105
105
std::atomic<AsyncTask *> waitQueue;
106
106
107
- explicit TaskGroupBase (uint64_t initialStatus)
107
+ const Metadata *successType;
108
+
109
+ explicit TaskGroupBase (const Metadata* T, uint64_t initialStatus)
108
110
: TaskGroupTaskStatusRecord(),
109
111
status(initialStatus),
110
- waitQueue(nullptr ) {}
112
+ waitQueue(nullptr ),
113
+ successType(T) {}
111
114
112
115
public:
113
116
virtual ~TaskGroupBase () {}
@@ -282,7 +285,7 @@ class TaskGroupBase : public TaskGroupTaskStatusRecord {
282
285
// / There can be only at-most-one waiting task on a group at any given time,
283
286
// / and the waiting task is expected to be the parent task in which the group
284
287
// / body is running.
285
- virtual PollResult tryEnqueueWaitingTask (AsyncTask *waitingTask) = 0 ;
288
+ PollResult tryEnqueueWaitingTask (AsyncTask *waitingTask);
286
289
287
290
// Enqueue the completed task onto ready queue if there are no waiting tasks yet
288
291
virtual void enqueueCompletedTask (AsyncTask *completedTask, bool hadErrorResult) = 0;
@@ -568,16 +571,13 @@ class AccumulatingTaskGroup: public TaskGroupBase {
568
571
// / AsyncTask.
569
572
NaiveTaskGroupQueue<ReadyQueueItem> readyQueue;
570
573
571
- const Metadata *successType;
572
-
573
574
friend class ::swift::AsyncTask;
574
575
575
576
public:
576
577
577
578
explicit AccumulatingTaskGroup (const Metadata *T)
578
- : TaskGroupBase(TaskGroupStatus::initial().status),
579
- readyQueue(),
580
- successType(T) {}
579
+ : TaskGroupBase(T, TaskGroupStatus::initial().status),
580
+ readyQueue() {}
581
581
582
582
virtual void destroy () override ;
583
583
@@ -653,9 +653,6 @@ class AccumulatingTaskGroup: public TaskGroupBase {
653
653
// / and the waitingTask eventually be woken up by a completion.
654
654
PollResult poll (AsyncTask *waitingTask);
655
655
656
- // / Attempt to store the waiting task, though if there is no pending tasks to wait for,
657
- // / or we're ready to complete the waiting task immediately, the PollResult will inform about that.
658
- virtual PollResult tryEnqueueWaitingTask (AsyncTask *waitingTask) override ;
659
656
};
660
657
661
658
/* *****************************************************************************/
@@ -688,16 +685,13 @@ class DiscardingTaskGroup: public TaskGroupBase {
688
685
// / however we use this queue to store errors from child tasks (currently at most one).
689
686
NaiveTaskGroupQueue<ReadyQueueItem> readyQueue;
690
687
691
- const Metadata *successType;
692
-
693
688
friend class ::swift::AsyncTask;
694
689
695
690
public:
696
691
697
692
explicit DiscardingTaskGroup (const Metadata *T)
698
- : TaskGroupBase(TaskGroupStatus::initial().status),
699
- readyQueue(),
700
- successType(T) {}
693
+ : TaskGroupBase(T, TaskGroupStatus::initial().status),
694
+ readyQueue() {}
701
695
702
696
virtual void destroy () override ;
703
697
@@ -799,8 +793,6 @@ class DiscardingTaskGroup: public TaskGroupBase {
799
793
// / and the waitingTask eventually be woken up by a completion.
800
794
PollResult poll (AsyncTask *waitingTask);
801
795
802
- virtual PollResult tryEnqueueWaitingTask (AsyncTask *waitingTask) override ;
803
-
804
796
bool offerBodyError (SwiftError* _Nonnull bodyError);
805
797
806
798
private:
@@ -1713,7 +1705,7 @@ bool DiscardingTaskGroup::offerBodyError(SwiftError* _Nonnull bodyError) {
1713
1705
return true ;
1714
1706
}
1715
1707
1716
- PollResult DiscardingTaskGroup ::tryEnqueueWaitingTask (AsyncTask *waitingTask) {
1708
+ PollResult TaskGroupBase ::tryEnqueueWaitingTask (AsyncTask *waitingTask) {
1717
1709
SWIFT_TASK_GROUP_DEBUG_LOG (this , " tryEnqueueWaitingTask, status = %s" , statusString ().c_str ());
1718
1710
PollResult result = PollResult::getEmpty (this ->successType );
1719
1711
result.storage = nullptr ;
@@ -1781,75 +1773,6 @@ PollResult DiscardingTaskGroup::tryEnqueueWaitingTask(AsyncTask *waitingTask) {
1781
1773
}
1782
1774
}
1783
1775
1784
- // FIXME: duplicated!!!!!!!!
1785
- PollResult AccumulatingTaskGroup::tryEnqueueWaitingTask (AsyncTask *waitingTask) {
1786
- SWIFT_TASK_GROUP_DEBUG_LOG (this , " tryEnqueueWaitingTask, status = %s" , statusString ().c_str ());
1787
- PollResult result = PollResult::getEmpty (this ->successType );
1788
- result.storage = nullptr ;
1789
- result.retainedTask = nullptr ;
1790
-
1791
- // Have we suspended the task?
1792
- bool hasSuspended = false ;
1793
- bool haveRunOneChildTaskInline = false ;
1794
-
1795
- reevaluate_if_TaskGroup_has_results:;
1796
- auto assumed = statusMarkWaitingAssumeAcquire ();
1797
- // ==== 1) bail out early if no tasks are pending ----------------------------
1798
- if (assumed.isEmpty (this )) {
1799
- SWIFT_TASK_DEBUG_LOG (" group(%p) waitAll, is empty, no pending tasks" , this );
1800
- // No tasks in flight, we know no tasks were submitted before this poll
1801
- // was issued, and if we parked here we'd potentially never be woken up.
1802
- // Bail out and return `nil` from `group.next()`.
1803
- statusRemoveWaitingRelease ();
1804
- return result;
1805
- }
1806
-
1807
- lock (); // TODO: remove pool lock, and use status for synchronization
1808
- auto waitHead = waitQueue.load (std::memory_order_acquire);
1809
-
1810
- // ==== 2) Add to wait queue -------------------------------------------------
1811
- _swift_tsan_release (static_cast <Job *>(waitingTask));
1812
- while (true ) {
1813
- if (!hasSuspended) {
1814
- hasSuspended = true ;
1815
- waitingTask->flagAsSuspended ();
1816
- }
1817
- // Put the waiting task at the beginning of the wait queue.
1818
- if (waitQueue.compare_exchange_strong (
1819
- waitHead, waitingTask,
1820
- /* success*/ std::memory_order_release,
1821
- /* failure*/ std::memory_order_acquire)) {
1822
- unlock (); // TODO: remove fragment lock, and use status for synchronization
1823
- #if SWIFT_CONCURRENCY_TASK_TO_THREAD_MODEL
1824
- // The logic here is paired with the logic in TaskGroupBase::offer. Once
1825
- // we run the
1826
- auto oldTask = _swift_task_clearCurrent ();
1827
- assert (oldTask == waitingTask);
1828
-
1829
- auto childTask = getTaskRecord ()->getFirstChild ();
1830
- assert (childTask != NULL );
1831
-
1832
- SWIFT_TASK_DEBUG_LOG (" [RunInline] Switching away from running %p to now running %p" , oldTask, childTask);
1833
- // Run the new task on the same thread now - this should run the new task to
1834
- // completion. All swift tasks in task-to-thread model run on generic
1835
- // executor
1836
- swift_job_run (childTask, ExecutorRef::generic ());
1837
- haveRunOneChildTaskInline = true ;
1838
-
1839
- SWIFT_TASK_DEBUG_LOG (" [RunInline] Switching back from running %p to now running %p" , childTask, oldTask);
1840
- // We are back to being the parent task and now that we've run the child
1841
- // task, we should reevaluate parent task
1842
- _swift_task_setCurrent (oldTask);
1843
- goto reevaluate_if_TaskGroup_has_results;
1844
- #endif
1845
- // no ready tasks, so we must wait.
1846
- result.status = PollStatus::MustWait;
1847
- _swift_task_clearCurrent ();
1848
- return result;
1849
- } // else, try again
1850
- }
1851
- }
1852
-
1853
1776
// =============================================================================
1854
1777
// ==== Task Group status and flag checks -------------------------------------
1855
1778
0 commit comments