[stdlib] SE-0472: Rename Task and*TaskGroup APIs to match the proposal

`Task.startSynchronously` -> `Task.immediate`
`*TaskGroup.startTaskSynchronously{UnlessCancelled}` -> `*TaskGroup.addImmediateTask{UnlessCancelled}`
This commit is contained in:
Pavel Yaskevich
2025-05-09 17:43:50 -07:00
parent 024dbd040f
commit 001eab867d
14 changed files with 140 additions and 140 deletions

View File

@@ -1,7 +1,7 @@
add_subdirectory(InternalShims)
gyb_expand(TaskGroup+addTask.swift.gyb TaskGroup+addTask.swift)
gyb_expand(Task+startSynchronously.swift.gyb Task+startSynchronously.swift)
gyb_expand(Task+immediate.swift.gyb Task+immediate.swift)
add_library(swift_Concurrency
Actor.cpp
@@ -97,7 +97,7 @@ add_library(swift_Concurrency
TaskSleep.swift
TaskSleepDuration.swift
"${CMAKE_CURRENT_BINARY_DIR}/TaskGroup+addTask.swift"
"${CMAKE_CURRENT_BINARY_DIR}/Task+startSynchronously.swift")
"${CMAKE_CURRENT_BINARY_DIR}/Task+immediate.swift")
include(${SwiftCore_CONCURRENCY_GLOBAL_EXECUTOR}.cmake)
target_compile_definitions(swift_Concurrency PRIVATE

View File

@@ -77,10 +77,10 @@ class SerialExecutorRef {
/// Executor that may need to participate in complex "same context" checks,
/// by invoking `isSameExclusiveExecutionContext` when comparing execution contexts.
ComplexEquality = 0b01,
/// Mark this executor as the one used by `Task.startSynchronously`,
/// Mark this executor as the one used by `Task.immediate`,
/// It cannot participate in switching.
// TODO: Perhaps make this a generic "cannot switch" rather than start synchronously specific.
StartSynchronously = 0b10,
Immediate = 0b10,
};
static_assert(static_cast<uintptr_t>(ExecutorKind::Ordinary) == 0);
@@ -107,12 +107,12 @@ public:
static SerialExecutorRef forSynchronousStart() {
auto wtable = reinterpret_cast<uintptr_t>(nullptr) |
static_cast<uintptr_t>(ExecutorKind::StartSynchronously);
static_cast<uintptr_t>(ExecutorKind::Immediate);
return SerialExecutorRef(nullptr, wtable);
}
bool isForSynchronousStart() const {
return getIdentity() == nullptr &&
getExecutorKind() == ExecutorKind::StartSynchronously;
getExecutorKind() == ExecutorKind::Immediate;
}
/// Given a pointer to a serial executor and its SerialExecutor

View File

@@ -2746,7 +2746,7 @@ public:
///
/// Supported starting in Swift 6.1.
Task_IsTaskFunctionConsumed = 15,
Task_IsStartSynchronouslyTask = 16,
Task_IsImmediateTask = 16,
};
explicit constexpr TaskCreateFlags(size_t bits) : FlagSet(bits) {}
@@ -2779,9 +2779,9 @@ public:
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsTaskFunctionConsumed,
isTaskFunctionConsumed,
setIsTaskFunctionConsumed)
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsStartSynchronouslyTask,
isSynchronousStartTask,
setIsSYnchronousStartTask)
FLAGSET_DEFINE_FLAG_ACCESSORS(Task_IsImmediateTask,
isImmediateTask,
setIsImmediateTask)
};
/// Flags for schedulable jobs.

View File

@@ -1063,7 +1063,7 @@ SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_task_startOnMainActor(AsyncTask* job);
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
void swift_task_startSynchronously(AsyncTask* job, SerialExecutorRef targetExecutor);
void swift_task_immediate(AsyncTask* job, SerialExecutorRef targetExecutor);
/// Donate this thread to the global executor until either the
/// given condition returns true or we've run out of cooperative

View File

@@ -439,7 +439,7 @@ OVERRIDE_TASK(task_startOnMainActor, void,
swift::, (AsyncTask *task), (task))
// In ACTOR since we need ExecutorTracking info
OVERRIDE_ACTOR(task_startSynchronously, void,
OVERRIDE_ACTOR(task_immediate, void,
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
swift::, (AsyncTask *task, SerialExecutorRef targetExecutor),
(task, targetExecutor))

View File

@@ -2511,8 +2511,8 @@ static void swift_task_switchImpl(SWIFT_ASYNC_CONTEXT AsyncContext *resumeContex
SWIFT_CC(swift)
static void
swift_task_startSynchronouslyImpl(AsyncTask *task,
SerialExecutorRef targetExecutor) {
swift_task_immediateImpl(AsyncTask *task,
SerialExecutorRef targetExecutor) {
swift_retain(task);
if (targetExecutor.isGeneric()) {
// If the target is generic, it means that the closure did not specify
@@ -2526,7 +2526,7 @@ swift_task_startSynchronouslyImpl(AsyncTask *task,
_swift_task_setCurrent(originalTask);
} else {
assert(swift_task_isCurrentExecutor(targetExecutor) &&
"startSynchronously must only be invoked when it is correctly in "
"'immediate' must only be invoked when it is correctly in "
"the same isolation already, but wasn't!");
// We can run synchronously, we're on the expected executor so running in

View File

@@ -223,7 +223,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
GYB_SOURCES
TaskGroup+addTask.swift.gyb
Task+startSynchronously.swift.gyb
Task+immediate.swift.gyb
SWIFT_MODULE_DEPENDS ${SWIFT_CONCURRENCY_DEPENDENCIES}
SWIFT_MODULE_DEPENDS_ANDROID Android

View File

@@ -13,7 +13,7 @@
import Swift
@_implementationOnly import SwiftConcurrencyInternalShims
// ==== Task.startSynchronously ------------------------------------------------
// ==== Task.immediate ---------------------------------------------------------
% METHOD_VARIANTS = [
% 'THROWING',
@@ -56,11 +56,11 @@ extension Task where Failure == ${FAILURE_TYPE} {
/// - Returns: A reference to the unstructured task which may be awaited on.
@available(SwiftStdlib 6.2, *)
@discardableResult
public static func startSynchronously(
public static func immediate(
name: String? = nil,
priority: TaskPriority? = nil,
% # NOTE: This closure cannot be 'sending' because we'll trigger ' pattern that the region based isolation checker does not understand how to check'
% # In this case: `func syncOnMyGlobalActor() { Task.startSynchronously { @MyGlobalActor in } }`
% # In this case: `func syncOnMyGlobalActor() { Task.immediate { @MyGlobalActor in } }`
@_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
) -> Task<Success, ${FAILURE_TYPE}> {
@@ -109,7 +109,7 @@ extension Task where Failure == ${FAILURE_TYPE} {
}
if canRunSynchronously {
_startTaskSynchronously(task!, targetExecutor: builtinSerialExecutor)
_startTaskImmediately(task!, targetExecutor: builtinSerialExecutor)
}
return Task<Success, ${FAILURE_TYPE}>(task!)
}
@@ -121,8 +121,8 @@ GROUP_AND_OP_INFO = [
(
'TaskGroup',
[
'startTaskSynchronously',
'startTaskSynchronouslyUnlessCancelled'
'addImmediateTask',
'addImmediateTaskUnlessCancelled'
],
'',
'ChildTaskResult'
@@ -130,8 +130,8 @@ GROUP_AND_OP_INFO = [
(
'ThrowingTaskGroup',
[
'startTaskSynchronously',
'startTaskSynchronouslyUnlessCancelled'
'addImmediateTask',
'addImmediateTaskUnlessCancelled'
],
'throws ',
'ChildTaskResult'
@@ -139,8 +139,8 @@ GROUP_AND_OP_INFO = [
(
'DiscardingTaskGroup',
[
'startTaskSynchronously',
'startTaskSynchronouslyUnlessCancelled'
'addImmediateTask',
'addImmediateTaskUnlessCancelled'
],
'',
'Void'
@@ -148,8 +148,8 @@ GROUP_AND_OP_INFO = [
(
'ThrowingDiscardingTaskGroup',
[
'startTaskSynchronously',
'startTaskSynchronouslyUnlessCancelled'
'addImmediateTask',
'addImmediateTaskUnlessCancelled'
],
'throws ',
'Void'
@@ -204,7 +204,7 @@ extension ${GROUP_TYPE} {
taskGroup: self._group,
operation: operation
)
_startTaskSynchronously(task, targetExecutor: builtinSerialExecutor)
_startTaskImmediately(task, targetExecutor: builtinSerialExecutor)
}
}
% end # METHOD_NAMES
@@ -264,5 +264,5 @@ extension Task where Failure == ${FAILURE_TYPE} {
@_silgen_name("swift_task_startOnMainActor")
internal func _startTaskOnMainActor(_ task: Builtin.NativeObject)
@_silgen_name("swift_task_startSynchronously")
internal func _startTaskSynchronously(_ task: Builtin.NativeObject, targetExecutor: Builtin.Executor?)
@_silgen_name("swift_task_immediate")
internal func _startTaskImmediately(_ task: Builtin.NativeObject, targetExecutor: Builtin.Executor?)

View File

@@ -109,24 +109,24 @@ func syncOnMyGlobalActor() -> [Task<Void, Never>] {
// This task must be guaranteed to happen AFTER 'tt' because we are already on this actor
// so this enqueue must happen after we give up the actor.
print("schedule Task { @MyGlobalActor }, before startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("schedule Task { @MyGlobalActor }, before immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
let t1 = Task { @MyGlobalActor in
print("inside Task { @MyGlobalActor }, after sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
}
print("before startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("before immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
let outerTID = getCurrentThreadID()
let tt = Task.startSynchronously { @MyGlobalActor in
let tt = Task.immediate { @MyGlobalActor in
let innerTID = getCurrentThreadID()
print("inside startSynchronously, outer thread = \(outerTID)")
print("inside startSynchronously, inner thread = \(innerTID)")
print("inside immediate, outer thread = \(outerTID)")
print("inside immediate, inner thread = \(innerTID)")
if (compareThreadIDs(outerTID, .notEqual, innerTID)) {
print("ERROR! Outer Thread ID must be equal Thread ID inside runSynchronously synchronous part!")
}
print("inside startSynchronously, sleep now [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, sleep now [thread:\(getCurrentThreadID())] @ :\(#line)")
_ = try? await Task.sleep(for: .seconds(1))
print("after sleep, inside startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("after sleep, inside immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
}
return [t1, tt]
@@ -138,18 +138,18 @@ func syncOnMyGlobalActorHopToDifferentActor() -> [Task<Void, Never>] {
// This task must be guaranteed to happen AFTER 'tt' because we are already on this actor
// so this enqueue must happen after we give up the actor.
print("schedule Task { @DifferentGlobalActor }, before startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("schedule Task { @DifferentGlobalActor }, before immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
let t1 = Task { @DifferentGlobalActor in
print("inside Task { @DifferentGlobalActor } [thread:\(getCurrentThreadID())] @ :\(#line)")
DifferentGlobalActor.shared.preconditionIsolated("Expected Task{} to be on DifferentGlobalActor")
}
print("before startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("before immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
let outerTID = getCurrentThreadID()
let tt = Task.startSynchronously { @DifferentGlobalActor in
let tt = Task.immediate { @DifferentGlobalActor in
let innerTID = getCurrentThreadID()
print("inside startSynchronously, outer thread = \(outerTID)")
print("inside startSynchronously, inner thread = \(innerTID)")
print("inside immediate, outer thread = \(outerTID)")
print("inside immediate, inner thread = \(innerTID)")
if (compareThreadIDs(outerTID, .equal, innerTID)) {
// This case specifically is NOT synchronously run because we specified a different isolation for the closure
// and FORCED a hop to the DifferentGlobalActor executor.
@@ -158,14 +158,14 @@ func syncOnMyGlobalActorHopToDifferentActor() -> [Task<Void, Never>] {
// We crucially need to see this task be enqueued on the different global actor,
// so it did not execute "synchronously" after all - it had to hop to the other actor.
dispatchPrecondition(condition: .onQueue(DifferentGlobalActor.queue))
DifferentGlobalActor.shared.preconditionIsolated("Expected Task.startSynchronously { @DifferentGlobalActor in } to be on DifferentGlobalActor")
DifferentGlobalActor.shared.preconditionIsolated("Expected Task.immediate { @DifferentGlobalActor in } to be on DifferentGlobalActor")
print("inside startSynchronously, sleep now [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, sleep now [thread:\(getCurrentThreadID())] @ :\(#line)")
_ = try? await Task.sleep(for: .milliseconds(100))
print("inside startSynchronously, after sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, after sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
dispatchPrecondition(condition: .onQueue(DifferentGlobalActor.queue))
DifferentGlobalActor.shared.preconditionIsolated("Expected Task.startSynchronously { @DifferentGlobalActor in } to be on DifferentGlobalActor")
DifferentGlobalActor.shared.preconditionIsolated("Expected Task.immediate { @DifferentGlobalActor in } to be on DifferentGlobalActor")
// do something here
await MyGlobalActor.test()
@@ -182,33 +182,33 @@ func syncOnNonTaskThread(synchronousTask behavior: SynchronousTaskBehavior) {
queue.async {
// This is in order so we don't have a "current task" nor any "current executor"
print("before startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("before immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
let outerTID = getCurrentThreadID()
let tt = Task.startSynchronously {
let tt = Task.immediate {
dispatchPrecondition(condition: .onQueue(queue))
let innerTID = getCurrentThreadID()
if compareThreadIDs(outerTID, .notEqual, innerTID) {
print("inside startSynchronously, outer thread = \(outerTID)")
print("inside startSynchronously, inner thread = \(innerTID)")
print("inside immediate, outer thread = \(outerTID)")
print("inside immediate, inner thread = \(innerTID)")
print("ERROR! Outer Thread ID must be equal Thread ID inside runSynchronously synchronous part!")
}
print("inside startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
switch behavior {
case .suspend:
// sleep until woken up by outer task; i.e. actually suspend
print("inside startSynchronously, before sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, before sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
_ = try? await Task.sleep(for: .seconds(10))
print("inside startSynchronously, after sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, after sleep [thread:\(getCurrentThreadID())] @ :\(#line)")
case .dontSuspend:
print("inside startSynchronously, done [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, done [thread:\(getCurrentThreadID())] @ :\(#line)")
()
}
sem1.signal()
}
print("after startSynchronously, outside; cancel (wakeup) the synchronous task! [thread:\(getCurrentThreadID())] @ :\(#line)")
print("after immediate, outside; cancel (wakeup) the synchronous task! [thread:\(getCurrentThreadID())] @ :\(#line)")
tt.cancel() // wake up the sleep
sem1.wait()
@@ -235,13 +235,13 @@ await Task { @MyGlobalActor in
// CHECK-LABEL: syncOnMyGlobalActor()
// CHECK: Confirmed to be on @MyGlobalActor
// CHECK: schedule Task { @MyGlobalActor }, before startSynchronously [thread:[[CALLING_THREAD:.*]]]
// CHECK: before startSynchronously [thread:[[CALLING_THREAD]]]
// CHECK: schedule Task { @MyGlobalActor }, before immediate [thread:[[CALLING_THREAD:.*]]]
// CHECK: before immediate [thread:[[CALLING_THREAD]]]
// CHECK-NOT: ERROR!
// CHECK: inside startSynchronously, sleep now
// CHECK: inside immediate, sleep now
// CHECK: inside Task { @MyGlobalActor }, after sleep
// resume on some other thread
// CHECK: after sleep, inside startSynchronously
// CHECK: after sleep, inside immediate
print("\n\n==== ------------------------------------------------------------------")
print("syncOnMyGlobalActorHopToDifferentActor()")
@@ -253,22 +253,22 @@ await Task { @MyGlobalActor in
}
}.value
// Assertion Notes: We expect the task to be on the specified queue as we force the Task.startSynchronously
// Assertion Notes: We expect the task to be on the specified queue as we force the Task.immediate
// task to enqueue on the DifferentGlobalActor, however we CANNOT use threads to verify this behavior,
// because dispatch may still pull tricks and reuse threads. We can only verify that we're on the right
// queue, and that the `enqueue` calls on the target executor happen when we expect them to.
//
// CHECK: syncOnMyGlobalActorHopToDifferentActor()
// CHECK: Confirmed to be on @MyGlobalActor
// CHECK: before startSynchronously
// CHECK: before immediate
// This IS actually enqueueing on the target actor (not synchronous), as expected:
// CHECK: NaiveQueueExecutor(DifferentGlobalActor-queue) enqueue
// CHECK: inside startSynchronously, sleep now
// CHECK: inside immediate, sleep now
// After the sleep we get back onto the specified executor as expected
// CHECK: NaiveQueueExecutor(DifferentGlobalActor-queue) enqueue
// CHECK: inside startSynchronously, after sleep
// CHECK: inside immediate, after sleep
print("\n\n==== ------------------------------------------------------------------")
var behavior: SynchronousTaskBehavior = .suspend
@@ -277,12 +277,12 @@ syncOnNonTaskThread(synchronousTask: behavior)
// CHECK-LABEL: syncOnNonTaskThread(synchronousTask: suspend)
// No interleaving allowed between "before" and "inside":
// CHECK-NEXT: before startSynchronously [thread:[[CALLING_THREAD2:.*]]]
// CHECK-NEXT: before immediate [thread:[[CALLING_THREAD2:.*]]]
// CHECK-NOT: ERROR!
// CHECK-NEXT: inside startSynchronously [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: inside startSynchronously, before sleep [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: after startSynchronously, outside; cancel (wakeup) the synchronous task! [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: inside startSynchronously, after sleep
// CHECK-NEXT: inside immediate [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: inside immediate, before sleep [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: after immediate, outside; cancel (wakeup) the synchronous task! [thread:[[CALLING_THREAD2]]]
// CHECK-NEXT: inside immediate, after sleep
print("\n\n==== ------------------------------------------------------------------")
behavior = .dontSuspend
@@ -290,11 +290,11 @@ print("syncOnNonTaskThread(synchronousTask: \(behavior))")
syncOnNonTaskThread(synchronousTask: behavior)
// CHECK-LABEL: syncOnNonTaskThread(synchronousTask: dontSuspend)
// CHECK-NEXT: before startSynchronously [thread:[[CALLING_THREAD3:.*]]]
// CHECK-NEXT: before immediate [thread:[[CALLING_THREAD3:.*]]]
// CHECK-NOT: ERROR!
// CHECK-NEXT: inside startSynchronously [thread:[[CALLING_THREAD3]]]
// CHECK: inside startSynchronously, done [thread:[[CALLING_THREAD3]]]
// CHECK: after startSynchronously, outside; cancel (wakeup) the synchronous task! [thread:[[CALLING_THREAD3]]]
// CHECK-NEXT: inside immediate [thread:[[CALLING_THREAD3]]]
// CHECK: inside immediate, done [thread:[[CALLING_THREAD3]]]
// CHECK: after immediate, outside; cancel (wakeup) the synchronous task! [thread:[[CALLING_THREAD3]]]
print("\n\n==== ------------------------------------------------------------------")
print("callActorFromStartSynchronousTask() - not on specific queue")
@@ -302,17 +302,17 @@ callActorFromStartSynchronousTask(recipient: .recipient(Recipient()))
// CHECK: callActorFromStartSynchronousTask()
// No interleaving allowed between "before" and "inside":
// CHECK: before startSynchronously [thread:[[CALLING_THREAD4:.*]]]
// CHECK-NEXT: inside startSynchronously [thread:[[CALLING_THREAD4]]]
// CHECK: before immediate [thread:[[CALLING_THREAD4:.*]]]
// CHECK-NEXT: inside immediate [thread:[[CALLING_THREAD4]]]
// It is important that as we suspend on the actor call, the 'after' startSynchronously gets to run
// CHECK-NEXT: inside startSynchronously, call rec.sync() [thread:[[CALLING_THREAD4]]]
// CHECK: after startSynchronously
// It is important that as we suspend on the actor call, the 'after' immediate gets to run
// CHECK-NEXT: inside immediate, call rec.sync() [thread:[[CALLING_THREAD4]]]
// CHECK: after immediate
// CHECK-NOT: ERROR!
// CHECK: inside startSynchronously, call rec.sync() done
// CHECK: inside immediate, call rec.sync() done
// CHECK-NOT: ERROR!
// CHECK: inside startSynchronously, done
// CHECK: inside immediate, done
/// Don't want to involve protocol calls to not confuse the test with additional details,
/// so we use concrete types here.
@@ -346,13 +346,13 @@ func callActorFromStartSynchronousTask(recipient rec: TargetActorToCall) {
queue.async {
let outerTID = getCurrentThreadID()
print("before startSynchronously [thread:\(outerTID)] @ :\(#line)")
let tt = Task.startSynchronously {
print("before immediate [thread:\(outerTID)] @ :\(#line)")
let tt = Task.immediate {
dispatchPrecondition(condition: .onQueue(queue))
let innerTID = getCurrentThreadID()
precondition(compareThreadIDs(outerTID, .equal, innerTID), "Outer Thread ID must be equal Thread ID inside runSynchronously synchronous part!")
print("inside startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
for i in 1..<10 {
queue.async {
@@ -360,12 +360,12 @@ func callActorFromStartSynchronousTask(recipient rec: TargetActorToCall) {
}
}
print("inside startSynchronously, call rec.sync() [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, call rec.sync() [thread:\(getCurrentThreadID())] @ :\(#line)")
switch rec {
case .recipient(let recipient): await recipient.callAndSuspend(syncTaskThreadID: innerTID)
case .recipientOnQueue(let recipient): await recipient.callAndSuspend(syncTaskThreadID: innerTID)
}
print("inside startSynchronously, call rec.sync() done [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, call rec.sync() done [thread:\(getCurrentThreadID())] @ :\(#line)")
// after suspension we are supposed to hop off to the global pool,
// thus the thread IDs cannot be the same anymore
@@ -378,11 +378,11 @@ func callActorFromStartSynchronousTask(recipient rec: TargetActorToCall) {
print("NOTICE: Task resumed on same thread as it entered the synchronous task!")
}
print("inside startSynchronously, done [thread:\(getCurrentThreadID())] @ :\(#line)")
print("inside immediate, done [thread:\(getCurrentThreadID())] @ :\(#line)")
sem1.signal()
}
print("after startSynchronously [thread:\(getCurrentThreadID())] @ :\(#line)")
print("after immediate [thread:\(getCurrentThreadID())] @ :\(#line)")
sem2.signal()
}
@@ -397,14 +397,14 @@ callActorFromStartSynchronousTask(recipient: .recipientOnQueue(RecipientOnQueue(
// 50: callActorFromStartSynchronousTask()
// 51: before startSynchronously [thread:0x00007000054f5000] @ :366
// 52: inside startSynchronously [thread:0x00007000054f5000] @ :372
// 53: inside startSynchronously, call rec.sync() [thread:0x00007000054f5000] @ :380
// 51: before immediate [thread:0x00007000054f5000] @ :366
// 52: inside immediate [thread:0x00007000054f5000] @ :372
// 53: inside immediate, call rec.sync() [thread:0x00007000054f5000] @ :380
// 54: Recipient/sync(syncTaskThreadID:) Current actor thread id = 0x000070000567e000 @ :336
// 55: inside startSynchronously, call rec.sync() done [thread:0x000070000567e000] @ :385
// 55: inside immediate, call rec.sync() done [thread:0x000070000567e000] @ :385
// 56: Inner thread id = 0x00007000054f5000
// 57: Current thread id = 0x000070000567e000
// 60: after startSynchronously [thread:0x00007000054f5000] @ :418
// 60: after immediate [thread:0x00007000054f5000] @ :418
// 61: - async work on queue
// 62: - async work on queue
// 63: - async work on queue
@@ -415,24 +415,24 @@ callActorFromStartSynchronousTask(recipient: .recipientOnQueue(RecipientOnQueue(
// 69: - async work on queue
// 71: Inner thread id = 0x00007000054f5000
// 72: Current thread id = 0x000070000567e000
// 73: inside startSynchronously, done [thread:0x000070000567e000] @ :414
// 73: inside immediate, done [thread:0x000070000567e000] @ :414
// CHECK-LABEL: callActorFromStartSynchronousTask() - actor in custom executor with its own queue
// No interleaving allowed between "before" and "inside":
// CHECK: before startSynchronously [thread:[[CALLING_THREAD4:.*]]]
// CHECK-NEXT: inside startSynchronously [thread:[[CALLING_THREAD4]]]
// CHECK: before immediate [thread:[[CALLING_THREAD4:.*]]]
// CHECK-NEXT: inside immediate [thread:[[CALLING_THREAD4]]]
// As we call into an actor, we must enqueue to its custom executor;
// Make sure the enqueue happens as expected and only then do we give up the calling thread
// allowing the 'after startSynchronously' to run.
// allowing the 'after immediate' to run.
//
// CHECK-NEXT: inside startSynchronously, call rec.sync() [thread:[[CALLING_THREAD4]]]
// CHECK: after startSynchronously
// CHECK-NEXT: inside immediate, call rec.sync() [thread:[[CALLING_THREAD4]]]
// CHECK: after immediate
// CHECK-NOT: ERROR!
// CHECK: inside startSynchronously, call rec.sync() done
// CHECK: inside immediate, call rec.sync() done
// CHECK-NOT: ERROR!
// CHECK: inside startSynchronously, done
// CHECK: inside immediate, done
actor RecipientOnQueue: RecipientProtocol {
let executor: NaiveQueueExecutor

View File

@@ -17,7 +17,7 @@ import _Concurrency
let max = 1000
func bar(x: Int, cc: CheckedContinuation<Void, Never>) {
Task.startSynchronously {
Task.immediate {
print("Task \(x) started")
try! await Task.sleep(nanoseconds: 10000)
if (x == max) {
@@ -61,4 +61,4 @@ await withCheckedContinuation { (cc: CheckedContinuation<Void, Never>) in
// CHECK: Task 27 started
// CHECK: Task 28 started
// CHECK: Task 29 started
// CHECK: Task 30 started
// CHECK: Task 30 started

View File

@@ -4,37 +4,37 @@
@available(SwiftStdlib 6.2, *)
func sync() -> Task<String, Never> {
Task.startSynchronously {
Task.immediate {
return ""
}
}
@available(SwiftStdlib 6.2, *)
func async() async throws {
let t1 = Task.startSynchronously {
let t1 = Task.immediate {
return ""
}
let _: String = await t1.value
let t2: Task<String, Error> = Task.startSynchronously {
let t2: Task<String, Error> = Task.immediate {
throw CancellationError()
}
let _: String = try await t2.value
await withTaskGroup(of: Int.self) { group in
group.startTaskSynchronously { 1 }
group.startTaskSynchronouslyUnlessCancelled { 2 }
group.addImmediateTask { 1 }
group.addImmediateTaskUnlessCancelled { 2 }
}
await withThrowingTaskGroup(of: Int.self) { group in
group.startTaskSynchronously { () async throws -> Int in 1 }
group.startTaskSynchronouslyUnlessCancelled { () async throws -> Int in 2 }
group.addImmediateTask { () async throws -> Int in 1 }
group.addImmediateTaskUnlessCancelled { () async throws -> Int in 2 }
}
await withDiscardingTaskGroup { group in
group.startTaskSynchronously { }
group.startTaskSynchronouslyUnlessCancelled { }
group.addImmediateTask { }
group.addImmediateTaskUnlessCancelled { }
}
try await withThrowingDiscardingTaskGroup { group in
group.startTaskSynchronously { () async throws -> Void in }
group.startTaskSynchronouslyUnlessCancelled { () async throws -> Void in }
group.addImmediateTask { () async throws -> Void in }
group.addImmediateTaskUnlessCancelled { () async throws -> Void in }
}
}

View File

@@ -389,20 +389,20 @@ Added: _$sScTss5NeverORszABRs_rlE4nameSSSgvgZ
Added: _$sScTss5NeverORszABRs_rlE4nameSSSgvpZMV
Added: _swift_task_getCurrentTaskName
// startSynchronously
Added: _swift_task_startSynchronously
Added: _$ss27ThrowingDiscardingTaskGroupV05startC13Synchronously4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$sScG22startTaskSynchronously4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScG37startTaskSynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaYAcntF
// startSynchronously, immediate, addImmediateTask{UnlessCancelled}
Added: _swift_task_immediate
Added: _$sScTss5Error_pRs_rlE18startSynchronously4name8priority_ScTyxsAA_pGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScTss5NeverORs_rlE18startSynchronously4name8priority_ScTyxABGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScg22startTaskSynchronously4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$sScg37startTaskSynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$ss19DiscardingTaskGroupV05startB13Synchronously4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss19DiscardingTaskGroupV05startB28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC13Synchronously4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$sScG16addImmediateTask4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScg31addImmediateTaskUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$sScG31addImmediateTaskUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScTss5NeverORs_rlE9immediate4name8priority_ScTyxABGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScTss5Error_pRs_rlE9immediate4name8priority_ScTyxsAA_pGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScg16addImmediateTask4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$ss19DiscardingTaskGroupV012addImmediateB04name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss19DiscardingTaskGroupV012addImmediateB15UnlessCancelled4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV012addImmediateC04name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV012addImmediateC15UnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
// isIsolatingCurrentContext
Added: _swift_task_invokeSwiftIsIsolatingCurrentContext

View File

@@ -389,20 +389,20 @@ Added: _$sScTss5NeverORszABRs_rlE4nameSSSgvgZ
Added: _$sScTss5NeverORszABRs_rlE4nameSSSgvpZMV
Added: _swift_task_getCurrentTaskName
// startSynchronously
Added: _swift_task_startSynchronously
Added: _$ss27ThrowingDiscardingTaskGroupV05startC13Synchronously4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$sScG22startTaskSynchronously4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScG37startTaskSynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaYAcntF
// startSynchronously, immediate, addImmediateTask{UnlessCancelled}
Added: _swift_task_immediate
Added: _$sScTss5Error_pRs_rlE18startSynchronously4name8priority_ScTyxsAA_pGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScTss5NeverORs_rlE18startSynchronously4name8priority_ScTyxABGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScg22startTaskSynchronously4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$sScg37startTaskSynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$ss19DiscardingTaskGroupV05startB13Synchronously4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss19DiscardingTaskGroupV05startB28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC13Synchronously4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV05startC28SynchronouslyUnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$sScG16addImmediateTask4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScg31addImmediateTaskUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$sScG31addImmediateTaskUnlessCancelled4name8priority9operationySSSg_ScPSgxyYaYAcntF
Added: _$sScTss5NeverORs_rlE9immediate4name8priority_ScTyxABGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScTss5Error_pRs_rlE9immediate4name8priority_ScTyxsAA_pGSSSg_ScPSgxyYaKYAcntFZ
Added: _$sScg16addImmediateTask4name8priority9operationySSSg_ScPSgxyYaKYAcntF
Added: _$ss19DiscardingTaskGroupV012addImmediateB04name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss19DiscardingTaskGroupV012addImmediateB15UnlessCancelled4name8priority9operationySSSg_ScPSgyyYaYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV012addImmediateC04name8priority9operationySSSg_ScPSgyyYaKYAcntF
Added: _$ss27ThrowingDiscardingTaskGroupV012addImmediateC15UnlessCancelled4name8priority9operationySSSg_ScPSgyyYaKYAcntF
// isIsolatingCurrentContext
Added: _swift_task_invokeSwiftIsIsolatingCurrentContext

View File

@@ -118,7 +118,7 @@ static void swift_task_startOnMainActor_override(AsyncTask* task) {
}
SWIFT_CC(swift)
static void swift_task_startSynchronously_override(AsyncTask* task, SerialExecutorRef targetExecutor) {
static void swift_task_immediate_override(AsyncTask* task, SerialExecutorRef targetExecutor) {
Ran = true;
}
@@ -350,8 +350,8 @@ TEST_F(CompatibilityOverrideConcurrencyTest, test_swift_startOnMainActorImpl) {
swift_task_startOnMainActor(nullptr);
}
TEST_F(CompatibilityOverrideConcurrencyTest, test_swift_startSynchronously) {
swift_task_startSynchronously(nullptr, SerialExecutorRef::generic());
TEST_F(CompatibilityOverrideConcurrencyTest, test_swift_immediately) {
swift_task_immediate(nullptr, SerialExecutorRef::generic());
}
TEST_F(CompatibilityOverrideConcurrencyTest,