Skip to content

Commit 51d9db6

Browse files
committed
Simplify swift_task_create_group_future_common API and rename it.
Collapse the `group` parameter of this API into the task options, and have existing callers set up the options appropriately. The goal for this function is to become the centralized entry point for all task creation, with an extensible interface.
1 parent 8bd2812 commit 51d9db6

File tree

4 files changed

+74
-46
lines changed

4 files changed

+74
-46
lines changed

include/swift/ABI/TaskOptions.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/ABI/MetadataValues.h"
2525
#include "swift/Runtime/Config.h"
2626
#include "swift/Basic/STLExtras.h"
27+
#include "llvm/Support/Casting.h"
2728

2829
namespace swift {
2930

@@ -34,14 +35,12 @@ namespace swift {
3435
/// to configure a newly spawned task.
3536
class TaskOptionRecord {
3637
public:
37-
TaskOptionRecordFlags Flags;
38+
const TaskOptionRecordFlags Flags;
3839
TaskOptionRecord *Parent;
3940

4041
TaskOptionRecord(TaskOptionRecordKind kind,
4142
TaskOptionRecord *parent = nullptr)
42-
: Flags(kind) {
43-
Parent = parent;
44-
}
43+
: Flags(kind), Parent(parent) { }
4544

4645
TaskOptionRecord(const TaskOptionRecord &) = delete;
4746
TaskOptionRecord &operator=(const TaskOptionRecord &) = delete;
@@ -53,15 +52,14 @@ class TaskOptionRecord {
5352
TaskOptionRecord *getParent() const {
5453
return Parent;
5554
}
56-
5755
};
5856

5957
/******************************************************************************/
6058
/****************************** TASK OPTIONS **********************************/
6159
/******************************************************************************/
6260

6361
class TaskGroupTaskOptionRecord : public TaskOptionRecord {
64-
TaskGroup *Group;
62+
TaskGroup * const Group;
6563

6664
public:
6765
TaskGroupTaskOptionRecord(TaskGroup *group)
@@ -71,6 +69,10 @@ class TaskGroupTaskOptionRecord : public TaskOptionRecord {
7169
TaskGroup *getGroup() const {
7270
return Group;
7371
}
72+
73+
static bool classof(const TaskOptionRecord *record) {
74+
return record->getKind() == TaskOptionRecordKind::TaskGroup;
75+
}
7476
};
7577

7678

@@ -80,7 +82,7 @@ class TaskGroupTaskOptionRecord : public TaskOptionRecord {
8082
/// executor should be used instead, most often this may mean the global
8183
/// concurrent executor, or the enclosing actor's executor.
8284
class ExecutorTaskOptionRecord : public TaskOptionRecord {
83-
ExecutorRef Executor;
85+
const ExecutorRef Executor;
8486

8587
public:
8688
ExecutorTaskOptionRecord(ExecutorRef executor)
@@ -90,6 +92,10 @@ class ExecutorTaskOptionRecord : public TaskOptionRecord {
9092
ExecutorRef getExecutor() const {
9193
return Executor;
9294
}
95+
96+
static bool classof(const TaskOptionRecord *record) {
97+
return record->getKind() == TaskOptionRecordKind::Executor;
98+
}
9399
};
94100

95101
} // end namespace swift

include/swift/Runtime/Concurrency.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ AsyncTaskAndContext swift_task_create_group_future_f(
8484
const Metadata *futureResultType,
8585
FutureAsyncSignature::FunctionType *function, size_t initialContextSize);
8686

87+
/// Create a task object.
88+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
89+
AsyncTaskAndContext swift_task_create(
90+
size_t flags,
91+
TaskOptionRecord *options,
92+
const Metadata *futureResultType,
93+
FutureAsyncSignature::FunctionType *function, void *closureContext,
94+
size_t initialContextSize);
95+
8796
/// Allocate memory in a task.
8897
///
8998
/// This must be called synchronously with the task.

stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ OVERRIDE_ACTOR(task_switch, void,
9696
TaskContinuationFunction *resumeFunction, ExecutorRef newExecutor),
9797
(resumeToContext, resumeFunction, newExecutor))
9898

99-
OVERRIDE_TASK(task_create_group_future_common, AsyncTaskAndContext, , , ,
99+
OVERRIDE_TASK(task_create, AsyncTaskAndContext,
100+
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
100101
(size_t flags,
101-
TaskGroup *group,
102102
TaskOptionRecord *options,
103103
const Metadata *futureResultType,
104104
FutureAsyncSignature::FunctionType *function,
105105
void *closureContext,
106106
size_t initialContextSize),
107-
(flags, group, options, futureResultType, function, closureContext,
107+
(flags, options, futureResultType, function, closureContext,
108108
initialContextSize))
109109

110110
OVERRIDE_TASK(task_future_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency),

stdlib/public/Concurrency/Task.cpp

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/Runtime/Concurrency.h"
1919
#include "swift/ABI/Task.h"
2020
#include "swift/ABI/TaskLocal.h"
21+
#include "swift/ABI/TaskOptions.h"
2122
#include "swift/ABI/Metadata.h"
2223
#include "swift/Runtime/Mutex.h"
2324
#include "swift/Runtime/HeapObject.h"
@@ -396,15 +397,15 @@ task_future_wait_resume_adapter(SWIFT_ASYNC_CONTEXT AsyncContext *_context) {
396397
return _context->ResumeParent(_context->Parent);
397398
}
398399

399-
/// All `swift_task_create*` variants funnel into this common implementation.
400+
/// Implementation of task creation.
400401
///
401402
/// If \p isAsyncLetTask is true, the \p closureContext is not heap allocated,
402403
/// but stack-allocated (and must not be ref-counted).
403404
/// Also, async-let tasks are not heap allocated, but allocated with the parent
404405
/// task's stack allocator.
405-
static AsyncTaskAndContext swift_task_create_group_future_commonImpl(
406+
SWIFT_CC(swift)
407+
static AsyncTaskAndContext swift_task_createImpl(
406408
size_t rawFlags,
407-
TaskGroup *group, // TODO: express as an option -- ktoso
408409
TaskOptionRecord *options,
409410
const Metadata *futureResultType,
410411
FutureAsyncSignature::FunctionType *function, void *closureContext,
@@ -415,6 +416,26 @@ static AsyncTaskAndContext swift_task_create_group_future_commonImpl(
415416
assert(!isAsyncLetTask || isAsyncLetTask == flags.task_isChildTask());
416417
assert(!flags.task_isFuture() ||
417418
initialContextSize >= sizeof(FutureAsyncContext));
419+
420+
// Collect the options we know about.
421+
ExecutorRef executor = ExecutorRef::generic();
422+
TaskGroup *group = nullptr;
423+
for (auto option = options; option; option = option->getParent()) {
424+
switch (option->getKind()) {
425+
case TaskOptionRecordKind::Executor:
426+
executor = cast<ExecutorTaskOptionRecord>(option)->getExecutor();
427+
break;
428+
429+
case TaskOptionRecordKind::TaskGroup:
430+
group = cast<TaskGroupTaskOptionRecord>(option)->getGroup();
431+
break;
432+
433+
default:
434+
// Ignore unknown options.
435+
break;
436+
}
437+
}
438+
418439
assert((group != nullptr) == flags.task_isGroupChildTask());
419440

420441
AsyncTask *parent = nullptr;
@@ -586,14 +607,6 @@ static AsyncTaskAndContext swift_task_create_group_future_commonImpl(
586607
return {task, initialContext};
587608
}
588609

589-
static AsyncTaskAndContext swift_task_create_group_future_common(
590-
size_t flags,
591-
TaskGroup *group,
592-
TaskOptionRecord *options,
593-
const Metadata *futureResultType,
594-
FutureAsyncSignature::FunctionType *function, void *closureContext,
595-
size_t initialContextSize);
596-
597610
AsyncTaskAndContext
598611
swift::swift_task_create_f(
599612
size_t flags,
@@ -625,12 +638,16 @@ AsyncTaskAndContext swift::swift_task_create_group_future_f(
625638
TaskOptionRecord *options,
626639
const Metadata *futureResultType,
627640
FutureAsyncSignature::FunctionType *function, size_t initialContextSize) {
628-
return swift_task_create_group_future_common(flags,
629-
group,
630-
options,
631-
futureResultType,
632-
function, /*closureContext=*/nullptr,
633-
initialContextSize);
641+
// Wire the group into the options.
642+
TaskGroupTaskOptionRecord groupRecord(group);
643+
if (group) {
644+
groupRecord.Parent = options;
645+
options = &groupRecord;
646+
}
647+
648+
return swift_task_create(
649+
flags, options, futureResultType, function, /*closureContext=*/nullptr,
650+
initialContextSize);
634651
}
635652

636653
/// Extract the entry point address and initial context size from an async closure value.
@@ -663,12 +680,8 @@ AsyncTaskAndContext swift::swift_task_create_future(
663680
SpecialPointerAuthDiscriminators::AsyncFutureFunction
664681
>(closureEntry, closureContext);
665682

666-
return swift_task_create_group_future_common(
667-
flags,
668-
/*group*/nullptr,
669-
options,
670-
futureResultType,
671-
taskEntry, closureContext,
683+
return swift_task_create(
684+
flags, options, futureResultType, taskEntry, closureContext,
672685
initialContextSize);
673686
}
674687

@@ -687,13 +700,9 @@ AsyncTaskAndContext swift::swift_task_create_async_let_future(
687700

688701
JobFlags flags(rawFlags);
689702
flags.task_setIsAsyncLetTask(true);
690-
return swift_task_create_group_future_common(
691-
flags.getOpaqueValue(),
692-
/*group*/nullptr,
693-
options,
694-
futureResultType,
695-
taskEntry, closureContext,
696-
initialContextSize);
703+
return swift_task_create(
704+
flags.getOpaqueValue(), options, futureResultType,
705+
taskEntry, closureContext, initialContextSize);
697706
}
698707

699708
AsyncTaskAndContext
@@ -711,12 +720,16 @@ swift::swift_task_create_group_future(
711720
FutureAsyncSignature,
712721
SpecialPointerAuthDiscriminators::AsyncFutureFunction
713722
>(closureEntry, closureContext);
714-
return swift_task_create_group_future_common(
715-
flags,
716-
group,
717-
options,
718-
futureResultType,
719-
taskEntry, closureContext,
723+
724+
// Wire the group into the options.
725+
TaskGroupTaskOptionRecord groupRecord(group);
726+
if (group) {
727+
groupRecord.Parent = options;
728+
options = &groupRecord;
729+
}
730+
731+
return swift_task_create(
732+
flags, options, futureResultType, taskEntry, closureContext,
720733
initialContextSize);
721734
}
722735

0 commit comments

Comments
 (0)