@@ -53,14 +53,19 @@ void FutureFragment::destroy() {
5353 }
5454}
5555
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) {
5761 using Status = FutureFragment::Status;
5862 using WaitQueueItem = FutureFragment::WaitQueueItem;
5963
6064 assert (isFuture ());
6165 auto fragment = futureFragment ();
6266
6367 auto queueHead = fragment->waitQueue .load (std::memory_order_acquire);
68+ bool contextIntialized = false ;
6469 while (true ) {
6570 switch (queueHead.getStatus ()) {
6671 case Status::Error:
@@ -83,6 +88,16 @@ FutureFragment::Status AsyncTask::waitFuture(AsyncTask *waitingTask) {
8388 break ;
8489 }
8590
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+
86101 // Put the waiting task at the beginning of the wait queue.
87102 waitingTask->getNextWaitingTask () = queueHead.getTask ();
88103 auto newQueueHead = WaitQueueItem::get (Status::Executing, waitingTask);
@@ -693,26 +708,22 @@ static void swift_task_future_waitImpl(
693708 waitingTask->ResumeTask = task_future_wait_resume_adapter;
694709 waitingTask->ResumeContext = callContext;
695710
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-
703711 // Wait on the future.
704712 assert (task->isFuture ());
705713
706- switch (task->waitFuture (waitingTask)) {
714+ switch (task->waitFuture (waitingTask, callContext, resumeFn, callerContext,
715+ result)) {
707716 case FutureFragment::Status::Executing:
708717 // The waiting task has been queued on the future.
709718 return ;
710719
711- case FutureFragment::Status::Success:
720+ case FutureFragment::Status::Success: {
712721 // 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+ }
716727
717728 case FutureFragment::Status::Error:
718729 swift_Concurrency_fatalError (0 , " future reported an error, but wait cannot throw" );
@@ -730,33 +741,31 @@ void swift_task_future_wait_throwingImpl(
730741 waitingTask->ResumeTask = task_wait_throwing_resume_adapter;
731742 waitingTask->ResumeContext = callContext;
732743
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);
740745
741746 // Wait on the future.
742747 assert (task->isFuture ());
743748
744- switch (task->waitFuture (waitingTask)) {
749+ switch (task->waitFuture (waitingTask, callContext, resumeFn, callerContext,
750+ result)) {
745751 case FutureFragment::Status::Executing:
746752 // The waiting task has been queued on the future.
747753 return ;
748754
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+ }
754761
755- case FutureFragment::Status::Error:
762+ case FutureFragment::Status::Error: {
756763 // 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+ }
760769 }
761770}
762771
0 commit comments