Skip to content

Commit 775a9bc

Browse files
authored
Merge pull request #81488 from xedin/rename-some-task-apis-6.2
[6.2][stdlib] SE-0472: Rename Task and*TaskGroup APIs to match the proposal
2 parents d42ec98 + b2e9620 commit 775a9bc

File tree

15 files changed

+348
-143
lines changed

15 files changed

+348
-143
lines changed

Runtimes/Core/Concurrency/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
add_subdirectory(InternalShims)
22

33
gyb_expand(TaskGroup+addTask.swift.gyb TaskGroup+addTask.swift)
4-
gyb_expand(Task+startSynchronously.swift.gyb Task+startSynchronously.swift)
4+
gyb_expand(Task+immediate.swift.gyb Task+immediate.swift)
55

66
add_library(swift_Concurrency
77
Actor.cpp
@@ -97,7 +97,7 @@ add_library(swift_Concurrency
9797
TaskSleep.swift
9898
TaskSleepDuration.swift
9999
"${CMAKE_CURRENT_BINARY_DIR}/TaskGroup+addTask.swift"
100-
"${CMAKE_CURRENT_BINARY_DIR}/Task+startSynchronously.swift")
100+
"${CMAKE_CURRENT_BINARY_DIR}/Task+immediate.swift")
101101

102102
include(${SwiftCore_CONCURRENCY_GLOBAL_EXECUTOR}.cmake)
103103
target_compile_definitions(swift_Concurrency PRIVATE

include/swift/ABI/Executor.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ class SerialExecutorRef {
7777
/// Executor that may need to participate in complex "same context" checks,
7878
/// by invoking `isSameExclusiveExecutionContext` when comparing execution contexts.
7979
ComplexEquality = 0b01,
80-
/// Mark this executor as the one used by `Task.startSynchronously`,
80+
/// Mark this executor as the one used by `Task.immediate`,
8181
/// It cannot participate in switching.
8282
// TODO: Perhaps make this a generic "cannot switch" rather than start synchronously specific.
83-
StartSynchronously = 0b10,
83+
Immediate = 0b10,
8484
};
8585

8686
static_assert(static_cast<uintptr_t>(ExecutorKind::Ordinary) == 0);
@@ -107,12 +107,12 @@ class SerialExecutorRef {
107107

108108
static SerialExecutorRef forSynchronousStart() {
109109
auto wtable = reinterpret_cast<uintptr_t>(nullptr) |
110-
static_cast<uintptr_t>(ExecutorKind::StartSynchronously);
110+
static_cast<uintptr_t>(ExecutorKind::Immediate);
111111
return SerialExecutorRef(nullptr, wtable);
112112
}
113113
bool isForSynchronousStart() const {
114114
return getIdentity() == nullptr &&
115-
getExecutorKind() == ExecutorKind::StartSynchronously;
115+
getExecutorKind() == ExecutorKind::Immediate;
116116
}
117117

118118
/// Given a pointer to a serial executor and its SerialExecutor

include/swift/ABI/MetadataValues.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2746,7 +2746,7 @@ class TaskCreateFlags : public FlagSet<size_t> {
27462746
///
27472747
/// Supported starting in Swift 6.1.
27482748
Task_IsTaskFunctionConsumed = 15,
2749-
Task_IsStartSynchronouslyTask = 16,
2749+
Task_IsImmediateTask = 16,
27502750
};
27512751

27522752
explicit constexpr TaskCreateFlags(size_t bits) : FlagSet(bits) {}
@@ -2779,9 +2779,9 @@ class TaskCreateFlags : public FlagSet<size_t> {
27792779
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsTaskFunctionConsumed,
27802780
isTaskFunctionConsumed,
27812781
setIsTaskFunctionConsumed)
2782-
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsStartSynchronouslyTask,
2783-
isSynchronousStartTask,
2784-
setIsSYnchronousStartTask)
2782+
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsImmediateTask,
2783+
isImmediateTask,
2784+
setIsImmediateTask)
27852785
};
27862786

27872787
/// Flags for schedulable jobs.

include/swift/Runtime/Concurrency.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
10631063
void swift_task_startOnMainActor(AsyncTask* job);
10641064

10651065
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
1066-
void swift_task_startSynchronously(AsyncTask* job);
1066+
void swift_task_immediate(AsyncTask* job, SerialExecutorRef targetExecutor);
10671067

10681068
/// Donate this thread to the global executor until either the
10691069
/// given condition returns true or we've run out of cooperative

stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,10 @@ OVERRIDE_TASK(task_startOnMainActor, void,
439439
swift::, (AsyncTask *task), (task))
440440

441441
// In ACTOR since we need ExecutorTracking info
442-
OVERRIDE_ACTOR(task_startSynchronously, void,
442+
OVERRIDE_ACTOR(task_immediate, void,
443443
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
444-
swift::, (AsyncTask *task), (task))
444+
swift::, (AsyncTask *task, SerialExecutorRef targetExecutor),
445+
(task, targetExecutor))
445446

446447
#undef OVERRIDE
447448
#undef OVERRIDE_ACTOR

stdlib/public/Concurrency/Actor.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,22 +2510,31 @@ static void swift_task_switchImpl(SWIFT_ASYNC_CONTEXT AsyncContext *resumeContex
25102510
}
25112511

25122512
SWIFT_CC(swift)
2513-
static void swift_task_startSynchronouslyImpl(AsyncTask* task) {
2513+
static void
2514+
swift_task_immediateImpl(AsyncTask *task,
2515+
SerialExecutorRef targetExecutor) {
25142516
swift_retain(task);
2515-
2516-
auto currentTracking = ExecutorTrackingInfo::current();
2517-
if (currentTracking) {
2518-
auto currentExecutor = currentTracking->getActiveExecutor();
2519-
AsyncTask * originalTask = _swift_task_clearCurrent();
2520-
2521-
swift_job_run(task, currentExecutor);
2522-
_swift_task_setCurrent(originalTask);
2517+
if (targetExecutor.isGeneric()) {
2518+
// If the target is generic, it means that the closure did not specify
2519+
// an isolation explicitly. According to the "start synchronously" rules,
2520+
// we should therefore ignore the global and just start running on the
2521+
// caller immediately.
2522+
SerialExecutorRef executor = SerialExecutorRef::forSynchronousStart();
2523+
2524+
auto originalTask = ActiveTask::swap(task);
2525+
swift_job_run(task, executor);
2526+
_swift_task_setCurrent(originalTask);
25232527
} else {
2524-
auto originalTask = ActiveTask::swap(task);
2525-
assert(!originalTask);
2528+
assert(swift_task_isCurrentExecutor(targetExecutor) &&
2529+
"'immediate' must only be invoked when it is correctly in "
2530+
"the same isolation already, but wasn't!");
2531+
2532+
// We can run synchronously, we're on the expected executor so running in
2533+
// the caller context is going to be in the same context as the requested
2534+
// "caller" context.
2535+
AsyncTask *originalTask = _swift_task_clearCurrent();
25262536

2527-
SerialExecutorRef executor = SerialExecutorRef::forSynchronousStart();
2528-
swift_job_run(task, executor);
2537+
swift_job_run(task, targetExecutor);
25292538
_swift_task_setCurrent(originalTask);
25302539
}
25312540
}

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
215215

216216
GYB_SOURCES
217217
TaskGroup+addTask.swift.gyb
218-
Task+startSynchronously.swift.gyb
218+
Task+immediate.swift.gyb
219219

220220
SWIFT_MODULE_DEPENDS_ANDROID Android
221221
SWIFT_MODULE_DEPENDS_LINUX Glibc

stdlib/public/Concurrency/Task+startSynchronously.swift.gyb renamed to stdlib/public/Concurrency/Task+immediate.swift.gyb

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import Swift
1414
@_implementationOnly import SwiftConcurrencyInternalShims
1515

16-
// ==== Task.startSynchronously ------------------------------------------------
16+
// ==== Task.immediate ---------------------------------------------------------
1717

1818
% METHOD_VARIANTS = [
1919
% 'THROWING',
@@ -32,6 +32,17 @@ import Swift
3232
@available(SwiftStdlib 6.2, *)
3333
extension Task where Failure == ${FAILURE_TYPE} {
3434

35+
@available(SwiftStdlib 6.2, *)
36+
@available(*, deprecated, renamed: "immediate")
37+
@discardableResult
38+
public static func startSynchronously(
39+
name: String? = nil,
40+
priority: TaskPriority? = nil,
41+
@_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
42+
) -> Task<Success, ${FAILURE_TYPE}> {
43+
immediate(name: name, priority: priority, operation)
44+
}
45+
3546
/// Create and immediately start running a new task in the context of the calling thread/task.
3647
///
3748
/// This function _starts_ the created task on the calling context.
@@ -56,17 +67,33 @@ extension Task where Failure == ${FAILURE_TYPE} {
5667
/// - Returns: A reference to the unstructured task which may be awaited on.
5768
@available(SwiftStdlib 6.2, *)
5869
@discardableResult
59-
public static func startSynchronously(
70+
public static func immediate(
6071
name: String? = nil,
6172
priority: TaskPriority? = nil,
62-
@_inheritActorContext @_implicitSelfCapture _ operation: __owned sending @escaping () async throws -> Success
73+
% # NOTE: This closure cannot be 'sending' because we'll trigger ' pattern that the region based isolation checker does not understand how to check'
74+
% # In this case: `func syncOnMyGlobalActor() { Task.immediate { @MyGlobalActor in } }`
75+
@_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
6376
) -> Task<Success, ${FAILURE_TYPE}> {
77+
78+
let builtinSerialExecutor =
79+
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
80+
81+
// Determine if we're switching isolation dynamically.
82+
// If not, we can run the task synchronously and therefore MUST NOT "enqueue" it.
83+
let flagsMustNotCrash: UInt64 = 0
84+
let canRunSynchronously: Bool =
85+
if let builtinSerialExecutor {
86+
_taskIsCurrentExecutor(executor: builtinSerialExecutor, flags: flagsMustNotCrash)
87+
} else {
88+
true // if there is not target executor, we can run synchronously
89+
}
90+
6491
let flags = taskCreateFlags(
6592
priority: priority,
6693
isChildTask: false,
6794
copyTaskLocals: true,
6895
inheritContext: true,
69-
enqueueJob: false, // don't enqueue, we'll run it manually
96+
enqueueJob: !canRunSynchronously,
7097
addPendingGroupTaskUnconditionally: false,
7198
isDiscardingTask: false,
7299
isSynchronousStart: true
@@ -79,6 +106,7 @@ extension Task where Failure == ${FAILURE_TYPE} {
79106
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
80107
Builtin.createTask(
81108
flags: flags,
109+
initialSerialExecutor: builtinSerialExecutor,
82110
taskName: nameBytes.baseAddress!._rawValue,
83111
operation: operation).0
84112
}
@@ -91,7 +119,9 @@ extension Task where Failure == ${FAILURE_TYPE} {
91119
operation: operation).0
92120
}
93121

94-
_startTaskSynchronously(task!)
122+
if canRunSynchronously {
123+
_startTaskImmediately(task!, targetExecutor: builtinSerialExecutor)
124+
}
95125
return Task<Success, ${FAILURE_TYPE}>(task!)
96126
}
97127
}
@@ -102,35 +132,35 @@ GROUP_AND_OP_INFO = [
102132
(
103133
'TaskGroup',
104134
[
105-
'startTaskSynchronously',
106-
'startTaskSynchronouslyUnlessCancelled'
135+
'addImmediateTask',
136+
'addImmediateTaskUnlessCancelled'
107137
],
108138
'',
109139
'ChildTaskResult'
110140
),
111141
(
112142
'ThrowingTaskGroup',
113143
[
114-
'startTaskSynchronously',
115-
'startTaskSynchronouslyUnlessCancelled'
144+
'addImmediateTask',
145+
'addImmediateTaskUnlessCancelled'
116146
],
117147
'throws ',
118148
'ChildTaskResult'
119149
),
120150
(
121151
'DiscardingTaskGroup',
122152
[
123-
'startTaskSynchronously',
124-
'startTaskSynchronouslyUnlessCancelled'
153+
'addImmediateTask',
154+
'addImmediateTaskUnlessCancelled'
125155
],
126156
'',
127157
'Void'
128158
),
129159
(
130160
'ThrowingDiscardingTaskGroup',
131161
[
132-
'startTaskSynchronously',
133-
'startTaskSynchronouslyUnlessCancelled'
162+
'addImmediateTask',
163+
'addImmediateTaskUnlessCancelled'
134164
],
135165
'throws ',
136166
'Void'
@@ -161,7 +191,7 @@ extension ${GROUP_TYPE} {
161191
public func ${METHOD_NAME}( // in ${GROUP_TYPE}
162192
name: String? = nil,
163193
priority: TaskPriority? = nil,
164-
operation: sending @escaping () async ${THROWS}-> ${RESULT_TYPE}
194+
@_inheritActorContext @_implicitSelfCapture operation: sending @isolated(any) @escaping () async ${THROWS}-> ${RESULT_TYPE}
165195
) {
166196
let flags = taskCreateFlags(
167197
priority: priority,
@@ -174,13 +204,18 @@ extension ${GROUP_TYPE} {
174204
isSynchronousStart: true
175205
)
176206

207+
// Create the asynchronous task.
208+
let builtinSerialExecutor =
209+
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
210+
177211
// Create the task in this group.
178212
let (task, _) = Builtin.createTask(
179213
flags: flags,
214+
initialSerialExecutor: builtinSerialExecutor,
180215
taskGroup: self._group,
181216
operation: operation
182217
)
183-
_startTaskSynchronously(task)
218+
_startTaskImmediately(task, targetExecutor: builtinSerialExecutor)
184219
}
185220
}
186221
% end # METHOD_NAMES
@@ -240,5 +275,5 @@ extension Task where Failure == ${FAILURE_TYPE} {
240275
@_silgen_name("swift_task_startOnMainActor")
241276
internal func _startTaskOnMainActor(_ task: Builtin.NativeObject)
242277

243-
@_silgen_name("swift_task_startSynchronously")
244-
internal func _startTaskSynchronously(_ task: Builtin.NativeObject)
278+
@_silgen_name("swift_task_immediate")
279+
internal func _startTaskImmediately(_ task: Builtin.NativeObject, targetExecutor: Builtin.Executor?)

stdlib/public/Concurrency/Task.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,8 +807,7 @@ extension Task where Failure == Error {
807807
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
808808

809809
let (task, _) = Builtin.createTask(flags: flags,
810-
initialSerialExecutor:
811-
builtinSerialExecutor,
810+
initialSerialExecutor: builtinSerialExecutor,
812811
operation: operation)
813812

814813
self._task = task

0 commit comments

Comments
 (0)