diff --git a/include/swift/ABI/TaskStatus.h b/include/swift/ABI/TaskStatus.h index 6e8f87680bbcc..56c05c3b6b5a2 100644 --- a/include/swift/ABI/TaskStatus.h +++ b/include/swift/ABI/TaskStatus.h @@ -164,14 +164,21 @@ class ChildTaskStatusRecord : public TaskStatusRecord { /// and are only tracked by their respective `TaskGroupTaskStatusRecord`. class TaskGroupTaskStatusRecord : public TaskStatusRecord { AsyncTask *FirstChild; + AsyncTask *LastChild; public: TaskGroupTaskStatusRecord() - : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), FirstChild(nullptr) { + : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), + FirstChild(nullptr), + LastChild(nullptr) { } TaskGroupTaskStatusRecord(AsyncTask *child) - : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), FirstChild(child) {} + : TaskStatusRecord(TaskStatusRecordKind::TaskGroup), + FirstChild(child), + LastChild(child) { + assert(!LastChild || !LastChild->childFragment()->getNextChild()); + } TaskGroup *getGroup() { return reinterpret_cast(this); } @@ -185,38 +192,28 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord { assert(child->hasGroupChildFragment()); assert(child->groupChildFragment()->getGroup() == getGroup()); + auto oldLastChild = LastChild; + LastChild = child; + if (!FirstChild) { // This is the first child we ever attach, so store it as FirstChild. FirstChild = child; return; } - // We need to traverse the siblings to find the last one and add the child - // there. - // FIXME: just set prepend to the current head, no need to traverse. - - auto cur = FirstChild; - while (cur) { - // no need to check hasChildFragment, all tasks we store here have them. - auto fragment = cur->childFragment(); - if (auto next = fragment->getNextChild()) { - cur = next; - } else { - // we're done searching and `cur` is the last - break; - } - } - - cur->childFragment()->setNextChild(child); + oldLastChild->childFragment()->setNextChild(child); } void detachChild(AsyncTask *child) { assert(child && "cannot remove a null child from group"); if (FirstChild == child) { FirstChild = getNextChildTask(child); + if (FirstChild == nullptr) { + LastChild = nullptr; + } return; } - + AsyncTask *prev = FirstChild; // Remove the child from the linked list, i.e.: // prev -> afterPrev -> afterChild @@ -230,6 +227,9 @@ class TaskGroupTaskStatusRecord : public TaskStatusRecord { if (afterPrev == child) { auto afterChild = getNextChildTask(child); prev->childFragment()->setNextChild(afterChild); + if (child == LastChild) { + LastChild = prev; + } return; }