24
24
25
25
using namespace swift ;
26
26
using FutureFragment = AsyncTask::FutureFragment;
27
+ using ChannelFragment = AsyncTask::ChannelFragment;
27
28
28
29
void FutureFragment::destroy () {
29
30
auto queueHead = waitQueue.load (std::memory_order_acquire);
@@ -41,10 +42,15 @@ void FutureFragment::destroy() {
41
42
}
42
43
}
43
44
44
- FutureFragment::Status AsyncTask::waitFuture (AsyncTask *waitingTask) {
45
+ FutureFragment::Status
46
+ AsyncTask::waitFuture (AsyncTask *waitingTask) {
45
47
using Status = FutureFragment::Status;
46
48
using WaitQueueItem = FutureFragment::WaitQueueItem;
47
49
50
+ // if (isChannel()) {
51
+ // assert(false && "waiting on channel!");
52
+ // }
53
+
48
54
assert (isFuture ());
49
55
auto fragment = futureFragment ();
50
56
@@ -263,15 +269,20 @@ AsyncTaskAndContext swift::swift_task_create_future_f(
263
269
initialContextSize >= sizeof (FutureAsyncContext));
264
270
assert ((parent != nullptr ) == flags.task_isChildTask ());
265
271
266
- // TODO: cleanup
267
- if (flags.task_isGroupChild ()) {
268
- assert (flags.task_isGroupChild () && flags.task_isChildTask ());
269
- assert (flags.task_isGroupChild () && parent->Flags .task_isChannel ());
272
+ if (flags.task_isGroupChild ()) { // TODO: express without the `if`?
273
+ assert (flags.task_isChildTask ());
274
+ assert (parent->Flags .task_isChannel ());
270
275
}
271
276
272
277
// Figure out the size of the header.
273
278
size_t headerSize = sizeof (AsyncTask);
274
- if (parent) headerSize += sizeof (AsyncTask::ChildFragment);
279
+ if (parent) {
280
+ headerSize += sizeof (AsyncTask::ChildFragment);
281
+ }
282
+
283
+ if (flags.task_isChannel ()) {
284
+ headerSize += ChannelFragment::fragmentSize ();
285
+ }
275
286
276
287
if (futureResultType) {
277
288
headerSize += FutureFragment::fragmentSize (futureResultType);
@@ -304,6 +315,12 @@ AsyncTaskAndContext swift::swift_task_create_future_f(
304
315
new (childFragment) AsyncTask::ChildFragment (parent);
305
316
}
306
317
318
+ // Initialize the channel fragment if applicable.
319
+ if (flags.task_isChannel ()) {
320
+ auto channelFragment = task->channelFragment ();
321
+ new (channelFragment) ChannelFragment (futureResultType);
322
+ }
323
+
307
324
// Initialize the future fragment if applicable.
308
325
if (futureResultType) {
309
326
auto futureFragment = task->futureFragment ();
@@ -314,18 +331,6 @@ AsyncTaskAndContext swift::swift_task_create_future_f(
314
331
auto futureContext = static_cast <FutureAsyncContext *>(initialContext);
315
332
futureContext->errorResult = nullptr ;
316
333
futureContext->indirectResult = futureFragment->getStoragePtr ();
317
-
318
- if (flags.task_isChannel ()) {
319
- auto parentChannelFragment = parent->channelFragment ();
320
- // new(channelFragment) ChannelFragment(futureResultType); // TODO make sure parent does init
321
- assert (parentChannelFragment && " group child task could not find parent channel fragment!" );
322
-
323
- //
324
- // // Set up the context for the future such that results ar *offered*
325
- // // into the channel fragment's message queue.
326
- // futureContext->indirectResult = parentChannelFragment;
327
- }
328
-
329
334
}
330
335
331
336
// Configure the initial context.
@@ -355,9 +360,16 @@ void swift::swift_task_future_wait(
355
360
waitingTask->ResumeTask = rawContext->ResumeParent ;
356
361
waitingTask->ResumeContext = rawContext;
357
362
358
- // Wait on the future.
359
363
auto context = static_cast <TaskFutureWaitAsyncContext *>(rawContext);
360
364
auto task = context->task ;
365
+
366
+ if (task->isChannel ()) {
367
+ // assert(false && "WAITING ON GROUP CHILD TASK");
368
+ swift::swift_task_channel_poll (waitingTask, executor, rawContext);
369
+ return ;
370
+ }
371
+
372
+ // Wait on the future.
361
373
assert (task->isFuture ());
362
374
switch (task->waitFuture (waitingTask)) {
363
375
case FutureFragment::Status::Executing:
0 commit comments