Skip to content

Commit 29176fc

Browse files
authored
Merge pull request #37885 from ktoso/wip-task-options
[Concurrency] Introduce TaskOptionRecord for spawn options
2 parents 4f6d00d + f37ae3d commit 29176fc

38 files changed

+398
-171
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,10 +2036,11 @@ class JobFlags : public FlagSet<uint32_t> {
20362036

20372037
// Kind-specific flags.
20382038

2039-
Task_IsChildTask = 24,
2040-
Task_IsFuture = 25,
2041-
Task_IsGroupChildTask = 26,
2042-
Task_IsContinuingAsyncTask = 27,
2039+
Task_IsChildTask = 24,
2040+
Task_IsFuture = 25,
2041+
Task_IsGroupChildTask = 26,
2042+
Task_IsContinuingAsyncTask = 27,
2043+
Task_IsAsyncLetTask = 28,
20432044
};
20442045

20452046
explicit JobFlags(uint32_t bits) : FlagSet(bits) {}
@@ -2072,6 +2073,9 @@ class JobFlags : public FlagSet<uint32_t> {
20722073
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsContinuingAsyncTask,
20732074
task_isContinuingAsyncTask,
20742075
task_setIsContinuingAsyncTask)
2076+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsAsyncLetTask,
2077+
task_isAsyncLetTask,
2078+
task_setIsAsyncLetTask)
20752079
};
20762080

20772081
/// Kinds of task status record.
@@ -2101,6 +2105,14 @@ enum class TaskStatusRecordKind : uint8_t {
21012105
Private_RecordLock = 192
21022106
};
21032107

2108+
/// Kinds of option records that can be passed to creating asynchronous tasks.
2109+
enum class TaskOptionRecordKind : uint8_t {
2110+
/// Request a task to be kicked off, or resumed, on a specific executor.
2111+
Executor = 0,
2112+
/// Request a child task to be part of a specific task group.
2113+
TaskGroup = 1,
2114+
};
2115+
21042116
/// Flags for cancellation records.
21052117
class TaskStatusRecordFlags : public FlagSet<size_t> {
21062118
public:
@@ -2119,6 +2131,24 @@ class TaskStatusRecordFlags : public FlagSet<size_t> {
21192131
getKind, setKind)
21202132
};
21212133

2134+
/// Flags for task option records.
2135+
class TaskOptionRecordFlags : public FlagSet<size_t> {
2136+
public:
2137+
enum {
2138+
Kind = 0,
2139+
Kind_width = 8,
2140+
};
2141+
2142+
explicit TaskOptionRecordFlags(size_t bits) : FlagSet(bits) {}
2143+
constexpr TaskOptionRecordFlags() {}
2144+
TaskOptionRecordFlags(TaskOptionRecordKind kind) {
2145+
setKind(kind);
2146+
}
2147+
2148+
FLAGSET_DEFINE_FIELD_ACCESSORS(Kind, Kind_width, TaskOptionRecordKind,
2149+
getKind, setKind)
2150+
};
2151+
21222152
/// Kinds of async context.
21232153
enum class AsyncContextKind {
21242154
/// An ordinary asynchronous function.

include/swift/ABI/Task.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class Job;
3434
struct OpaqueValue;
3535
struct SwiftError;
3636
class TaskStatusRecord;
37+
class TaskOptionRecord;
3738
class TaskGroup;
3839

3940
extern FullMetadata<DispatchClassMetadata> jobHeapMetadata;
@@ -537,6 +538,8 @@ inline void Job::runInFullyEstablishedContext() {
537538
return runSimpleInFullyEstablishedContext(); // 'return' forces tail call
538539
}
539540

541+
// ==== ------------------------------------------------------------------------
542+
540543
/// An asynchronous context within a task. Generally contexts are
541544
/// allocated using the task-local stack alloc/dealloc operations, but
542545
/// there's no guarantee of that, and the ABI is designed to permit

include/swift/ABI/TaskLocal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// Swift ABI describing tasks.
13+
// Swift ABI describing task locals.
1414
//
1515
//===----------------------------------------------------------------------===//
1616

include/swift/ABI/TaskOptions.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===--- TaskOptions.h - ABI structures for task options --------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Swift ABI describing task options.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_ABI_TASK_OPTIONS_H
18+
#define SWIFT_ABI_TASK_OPTIONS_H
19+
20+
#include "swift/ABI/TaskLocal.h"
21+
#include "swift/ABI/Executor.h"
22+
#include "swift/ABI/HeapObject.h"
23+
#include "swift/ABI/Metadata.h"
24+
#include "swift/ABI/MetadataValues.h"
25+
#include "swift/Runtime/Config.h"
26+
#include "swift/Basic/STLExtras.h"
27+
28+
namespace swift {
29+
30+
// ==== ------------------------------------------------------------------------
31+
// ==== Task Options, for creating and waiting on tasks
32+
33+
/// The abstract base class for all options that may be used
34+
/// to configure a newly spawned task.
35+
class TaskOptionRecord {
36+
public:
37+
TaskOptionRecordFlags Flags;
38+
TaskOptionRecord *Parent;
39+
40+
TaskOptionRecord(TaskOptionRecordKind kind,
41+
TaskOptionRecord *parent = nullptr)
42+
: Flags(kind) {
43+
Parent = parent;
44+
}
45+
46+
TaskOptionRecord(const TaskOptionRecord &) = delete;
47+
TaskOptionRecord &operator=(const TaskOptionRecord &) = delete;
48+
49+
TaskOptionRecordKind getKind() const {
50+
return Flags.getKind();
51+
}
52+
53+
TaskOptionRecord *getParent() const {
54+
return Parent;
55+
}
56+
57+
};
58+
59+
/******************************************************************************/
60+
/****************************** TASK OPTIONS **********************************/
61+
/******************************************************************************/
62+
63+
class TaskGroupTaskOptionRecord : public TaskOptionRecord {
64+
TaskGroup *Group;
65+
66+
public:
67+
TaskGroupTaskOptionRecord(TaskGroup *group)
68+
: TaskOptionRecord(TaskOptionRecordKind::TaskGroup),
69+
Group(group) {}
70+
71+
TaskGroup *getGroup() const {
72+
return Group;
73+
}
74+
};
75+
76+
77+
/// Task option to specify on what executor the task should be executed.
78+
///
79+
/// Not passing this option implies that that a "best guess" or good default
80+
/// executor should be used instead, most often this may mean the global
81+
/// concurrent executor, or the enclosing actor's executor.
82+
class ExecutorTaskOptionRecord : public TaskOptionRecord {
83+
ExecutorRef *Executor;
84+
85+
public:
86+
ExecutorTaskOptionRecord(ExecutorRef *executor)
87+
: TaskOptionRecord(TaskOptionRecordKind::Executor),
88+
Executor(executor) {}
89+
90+
ExecutorRef *getExecutor() const {
91+
return Executor;
92+
}
93+
};
94+
95+
} // end namespace swift
96+
97+
#endif

include/swift/AST/Builtins.def

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,9 @@ BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)
806806
BUILTIN_MISC_OPERATION_WITH_SILGEN(EndAsyncLet, "endAsyncLet", "", Special)
807807

808808
/// createAsyncTaskFuture(): (
809-
/// Int, Builtin.NativeObject?, @escaping () async throws -> T
809+
/// Int, // flags
810+
/// Builtin.RawPointer?, // options (TaskOptionRecord*)
811+
/// @escaping () async throws -> T // function
810812
/// ) -> Builtin.NativeObject
811813
///
812814
/// Create a new asynchronous task future, given flags, an (optional) parent
@@ -815,10 +817,10 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskFuture,
815817
"createAsyncTaskFuture", "", Special)
816818

817819
/// createAsyncTaskGroupFuture(): (
818-
/// Int, // flags
819-
/// Builtin.NativeObject?, // parent
820-
/// Builtin.RawPointer?, // group
821-
/// @escaping () async throws -> T
820+
/// Int, // flags
821+
/// Builtin.RawPointer?, // group
822+
/// Builtin.RawPointer?, // options (TaskOptionRecord*)
823+
/// @escaping () async throws -> T // function
822824
/// ) -> Builtin.NativeObject
823825
///
824826
/// Create a new asynchronous task future, given flags, a parent task,

include/swift/Runtime/Concurrency.h

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
namespace swift {
2929
class DefaultActor;
30+
class TaskOptionRecord;
3031

3132
struct SwiftError;
3233

@@ -35,54 +36,53 @@ struct AsyncTaskAndContext {
3536
AsyncContext *InitialContext;
3637
};
3738

38-
/// Create a task object with no future which will run the given
39-
/// function.
39+
/// Create a task object with no future which will run the given function.
4040
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
41-
AsyncTaskAndContext swift_task_create_f(size_t flags,
42-
ThinNullaryAsyncSignature::FunctionType *function,
43-
size_t initialContextSize);
41+
AsyncTaskAndContext swift_task_create_f(
42+
size_t flags,
43+
TaskOptionRecord *options,
44+
ThinNullaryAsyncSignature::FunctionType *function, size_t initialContextSize);
4445

4546
/// Caution: not all future-initializing functions actually throw, so
4647
/// this signature may be incorrect.
4748
using FutureAsyncSignature =
4849
AsyncSignature<void(void*), /*throws*/ true>;
4950

50-
/// Create a task object with a future which will run the given
51-
/// closure.
51+
/// Create a task object with a future which will run the given closure.
5252
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
5353
AsyncTaskAndContext swift_task_create_future(
5454
size_t flags,
55+
TaskOptionRecord *options,
5556
const Metadata *futureResultType,
56-
void *closureEntryPoint,
57-
HeapObject * /* +1 */ closureContext);
57+
void *closureEntryPoint, HeapObject * /* +1 */ closureContext);
5858

59-
/// Create a task object with a future which will run the given
60-
/// function.
59+
/// Create a task object with a future which will run the given function.
6160
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
6261
AsyncTaskAndContext swift_task_create_future_f(
6362
size_t flags,
63+
TaskOptionRecord *options,
6464
const Metadata *futureResultType,
65-
FutureAsyncSignature::FunctionType *function,
66-
size_t initialContextSize);
65+
FutureAsyncSignature::FunctionType *function, size_t initialContextSize);
6766

6867
/// Create a task object with a future which will run the given
6968
/// closure, and offer its result to the task group
7069
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
7170
AsyncTaskAndContext swift_task_create_group_future(
72-
size_t flags, TaskGroup *group,
71+
size_t flags,
72+
TaskGroup *group,
73+
TaskOptionRecord *options,
7374
const Metadata *futureResultType,
74-
void *closureEntryPoint,
75-
HeapObject * /* +1 */ closureContext);
75+
void *closureEntryPoint, HeapObject * /* +1 */ closureContext);
7676

7777
/// Create a task object with a future which will run the given
7878
/// function, and offer its result to the task group
7979
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
8080
AsyncTaskAndContext swift_task_create_group_future_f(
8181
size_t flags,
8282
TaskGroup *group,
83+
TaskOptionRecord *options,
8384
const Metadata *futureResultType,
84-
FutureAsyncSignature::FunctionType *function,
85-
size_t initialContextSize);
85+
FutureAsyncSignature::FunctionType *function, size_t initialContextSize);
8686

8787
/// Allocate memory in a task.
8888
///
@@ -270,16 +270,16 @@ bool swift_taskGroup_isEmpty(TaskGroup *group);
270270
///
271271
/// \code
272272
/// func swift_asyncLet_start<T>(
273-
/// _ alet: Builtin.RawPointer,
273+
/// asyncLet: Builtin.RawPointer,
274+
/// options: Builtin.RawPointer?,
274275
/// operation: __owned @Sendable () async throws -> T
275276
/// )
276277
/// \endcode
277278
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
278-
void swift_asyncLet_start(
279-
AsyncLet *alet,
280-
const Metadata *futureResultType,
281-
void *closureEntryPoint,
282-
void *closureContext);
279+
void swift_asyncLet_start(AsyncLet *alet,
280+
TaskOptionRecord *options,
281+
const Metadata *futureResultType,
282+
void *closureEntryPoint, void *closureContext);
283283

284284
/// This matches the ABI of a closure `<T>(Builtin.RawPointer) async -> T`
285285
using AsyncLetWaitSignature =

0 commit comments

Comments
 (0)