mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #81428 from xedin/rename-some-task-apis
[stdlib] SE-0472: Rename `Task` and`*TaskGroup` APIs to match the pro…
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import Swift
|
||||
@_implementationOnly import SwiftConcurrencyInternalShims
|
||||
|
||||
// ==== Task.startSynchronously ------------------------------------------------
|
||||
// ==== Task.immediate ---------------------------------------------------------
|
||||
|
||||
% METHOD_VARIANTS = [
|
||||
% 'THROWING',
|
||||
@@ -32,6 +32,17 @@ import Swift
|
||||
@available(SwiftStdlib 6.2, *)
|
||||
extension Task where Failure == ${FAILURE_TYPE} {
|
||||
|
||||
@available(SwiftStdlib 6.2, *)
|
||||
@available(*, deprecated, renamed: "immediate")
|
||||
@discardableResult
|
||||
public static func startSynchronously(
|
||||
name: String? = nil,
|
||||
priority: TaskPriority? = nil,
|
||||
@_implicitSelfCapture _ operation: __owned @isolated(any) @escaping () async throws -> Success
|
||||
) -> Task<Success, ${FAILURE_TYPE}> {
|
||||
immediate(name: name, priority: priority, operation)
|
||||
}
|
||||
|
||||
/// Create and immediately start running a new task in the context of the calling thread/task.
|
||||
///
|
||||
/// This function _starts_ the created task on the calling context.
|
||||
@@ -56,11 +67,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 +120,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 +132,8 @@ GROUP_AND_OP_INFO = [
|
||||
(
|
||||
'TaskGroup',
|
||||
[
|
||||
'startTaskSynchronously',
|
||||
'startTaskSynchronouslyUnlessCancelled'
|
||||
'addImmediateTask',
|
||||
'addImmediateTaskUnlessCancelled'
|
||||
],
|
||||
'',
|
||||
'ChildTaskResult'
|
||||
@@ -130,8 +141,8 @@ GROUP_AND_OP_INFO = [
|
||||
(
|
||||
'ThrowingTaskGroup',
|
||||
[
|
||||
'startTaskSynchronously',
|
||||
'startTaskSynchronouslyUnlessCancelled'
|
||||
'addImmediateTask',
|
||||
'addImmediateTaskUnlessCancelled'
|
||||
],
|
||||
'throws ',
|
||||
'ChildTaskResult'
|
||||
@@ -139,8 +150,8 @@ GROUP_AND_OP_INFO = [
|
||||
(
|
||||
'DiscardingTaskGroup',
|
||||
[
|
||||
'startTaskSynchronously',
|
||||
'startTaskSynchronouslyUnlessCancelled'
|
||||
'addImmediateTask',
|
||||
'addImmediateTaskUnlessCancelled'
|
||||
],
|
||||
'',
|
||||
'Void'
|
||||
@@ -148,8 +159,8 @@ GROUP_AND_OP_INFO = [
|
||||
(
|
||||
'ThrowingDiscardingTaskGroup',
|
||||
[
|
||||
'startTaskSynchronously',
|
||||
'startTaskSynchronouslyUnlessCancelled'
|
||||
'addImmediateTask',
|
||||
'addImmediateTaskUnlessCancelled'
|
||||
],
|
||||
'throws ',
|
||||
'Void'
|
||||
@@ -204,7 +215,7 @@ extension ${GROUP_TYPE} {
|
||||
taskGroup: self._group,
|
||||
operation: operation
|
||||
)
|
||||
_startTaskSynchronously(task, targetExecutor: builtinSerialExecutor)
|
||||
_startTaskImmediately(task, targetExecutor: builtinSerialExecutor)
|
||||
}
|
||||
}
|
||||
% end # METHOD_NAMES
|
||||
@@ -264,5 +275,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?)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user