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