@@ -53,14 +53,19 @@ void FutureFragment::destroy() {
53
53
}
54
54
}
55
55
56
- FutureFragment::Status AsyncTask::waitFuture (AsyncTask *waitingTask) {
56
+ FutureFragment::Status AsyncTask::waitFuture (AsyncTask *waitingTask,
57
+ AsyncContext *waitingTaskContext,
58
+ TaskContinuationFunction *resumeFn,
59
+ AsyncContext *callerContext,
60
+ OpaqueValue *result) {
57
61
using Status = FutureFragment::Status;
58
62
using WaitQueueItem = FutureFragment::WaitQueueItem;
59
63
60
64
assert (isFuture ());
61
65
auto fragment = futureFragment ();
62
66
63
67
auto queueHead = fragment->waitQueue .load (std::memory_order_acquire);
68
+ bool contextIntialized = false ;
64
69
while (true ) {
65
70
switch (queueHead.getStatus ()) {
66
71
case Status::Error:
@@ -83,6 +88,16 @@ FutureFragment::Status AsyncTask::waitFuture(AsyncTask *waitingTask) {
83
88
break ;
84
89
}
85
90
91
+ if (!contextIntialized) {
92
+ contextIntialized = true ;
93
+ auto context =
94
+ reinterpret_cast <TaskFutureWaitAsyncContext *>(waitingTaskContext);
95
+ context->errorResult = nullptr ;
96
+ context->successResultPointer = result;
97
+ context->ResumeParent = resumeFn;
98
+ context->Parent = callerContext;
99
+ }
100
+
86
101
// Put the waiting task at the beginning of the wait queue.
87
102
waitingTask->getNextWaitingTask () = queueHead.getTask ();
88
103
auto newQueueHead = WaitQueueItem::get (Status::Executing, waitingTask);
@@ -693,26 +708,22 @@ static void swift_task_future_waitImpl(
693
708
waitingTask->ResumeTask = task_future_wait_resume_adapter;
694
709
waitingTask->ResumeContext = callContext;
695
710
696
- // Stash the result pointer for when we resume later.
697
- auto context = static_cast <TaskFutureWaitAsyncContext *>(callContext);
698
- context->ResumeParent = resumeFn;
699
- context->Parent = callerContext;
700
- context->successResultPointer = result;
701
- context->errorResult = nullptr ;
702
-
703
711
// Wait on the future.
704
712
assert (task->isFuture ());
705
713
706
- switch (task->waitFuture (waitingTask)) {
714
+ switch (task->waitFuture (waitingTask, callContext, resumeFn, callerContext,
715
+ result)) {
707
716
case FutureFragment::Status::Executing:
708
717
// The waiting task has been queued on the future.
709
718
return ;
710
719
711
- case FutureFragment::Status::Success:
720
+ case FutureFragment::Status::Success: {
712
721
// Run the task with a successful result.
713
- context->fillWithSuccess (task->futureFragment ());
714
- // FIXME: force tail call
715
- return waitingTask->runInFullyEstablishedContext ();
722
+ auto future = task->futureFragment ();
723
+ future->getResultType ()->vw_initializeWithCopy (result,
724
+ future->getStoragePtr ());
725
+ return resumeFn (callerContext);
726
+ }
716
727
717
728
case FutureFragment::Status::Error:
718
729
swift_Concurrency_fatalError (0 , " future reported an error, but wait cannot throw" );
@@ -730,33 +741,31 @@ void swift_task_future_wait_throwingImpl(
730
741
waitingTask->ResumeTask = task_wait_throwing_resume_adapter;
731
742
waitingTask->ResumeContext = callContext;
732
743
733
- // Stash the result pointer for when we resume later.
734
- auto context = static_cast <TaskFutureWaitAsyncContext *>(callContext);
735
- context->ResumeParent =
736
- reinterpret_cast <TaskContinuationFunction *>(resumeFunction);
737
- context->Parent = callerContext;
738
- context->successResultPointer = result;
739
- context->errorResult = nullptr ;
744
+ auto resumeFn = reinterpret_cast <TaskContinuationFunction *>(resumeFunction);
740
745
741
746
// Wait on the future.
742
747
assert (task->isFuture ());
743
748
744
- switch (task->waitFuture (waitingTask)) {
749
+ switch (task->waitFuture (waitingTask, callContext, resumeFn, callerContext,
750
+ result)) {
745
751
case FutureFragment::Status::Executing:
746
752
// The waiting task has been queued on the future.
747
753
return ;
748
754
749
- case FutureFragment::Status::Success:
750
- // Run the task with a successful result.
751
- context->fillWithSuccess (task->futureFragment ());
752
- // FIXME: force tail call
753
- return waitingTask->runInFullyEstablishedContext ();
755
+ case FutureFragment::Status::Success: {
756
+ auto future = task->futureFragment ();
757
+ future->getResultType ()->vw_initializeWithCopy (result,
758
+ future->getStoragePtr ());
759
+ return resumeFunction (callerContext, nullptr /* error*/ );
760
+ }
754
761
755
- case FutureFragment::Status::Error:
762
+ case FutureFragment::Status::Error: {
756
763
// Run the task with an error result.
757
- context->fillWithError (task->futureFragment ());
758
- // FIXME: force tail call
759
- return waitingTask->runInFullyEstablishedContext ();
764
+ auto future = task->futureFragment ();
765
+ auto error = future->getError ();
766
+ swift_errorRetain (error);
767
+ return resumeFunction (callerContext, error);
768
+ }
760
769
}
761
770
}
762
771
0 commit comments