[6.2][Concurrency][SE-review update] Task names update (#81132)

**Description**: This adds "task name" parameter to all task creating
functions.

This is done in a few ways, e.g. we can backdeploy this to 5.1 in APIs
which do not accept the `TaskExecutor` but it they do we provide a
version for 6.0+ etc. This was requested in the SE acceptable of this
proposal [Acceptance post
SE-0469](https://forums.swift.org/t/accepted-with-modifications-se-0469-task-naming/79438).

This moves all these declarations to gyb since going through them one by
one has become unmaintainable otherwise.

**Scope/Impact**: All task creation APIs now gain a new task name
parameter.
**Risk:** Medium, changes existing APIs rather than adding "even more
overloads" though this risk was discussed in the team and accepted. This
has a potential to be source breaking it someone used Task.init and
friends as function.
**Testing**: CI testing, source compatibility suite testing
**Reviewed by**: 

**Original PR:** 
- https://github.com/swiftlang/swift/pull/81107 build changes required
for this
- https://github.com/swiftlang/swift/pull/80984


**Radar:**

---------

Co-authored-by: Kuba Mracek <mracek@apple.com>
This commit is contained in:
Konrad `ktoso` Malawski
2025-05-29 07:52:33 +09:00
committed by GitHub
parent 28360605e7
commit c8a8183d26
15 changed files with 585 additions and 1361 deletions

View File

@@ -1,5 +1,6 @@
add_subdirectory(InternalShims)
gyb_expand(Task+init.swift.gyb Task+init.swift)
gyb_expand(TaskGroup+addTask.swift.gyb TaskGroup+addTask.swift)
gyb_expand(Task+immediate.swift.gyb Task+immediate.swift)
@@ -92,10 +93,10 @@ add_library(swift_Concurrency
Task+TaskExecutor.swift
TaskCancellation.swift
TaskGroup.swift
TaskGroup+Embedded.swift
TaskLocal.swift
TaskSleep.swift
TaskSleepDuration.swift
"${CMAKE_CURRENT_BINARY_DIR}/Task+init.swift"
"${CMAKE_CURRENT_BINARY_DIR}/TaskGroup+addTask.swift"
"${CMAKE_CURRENT_BINARY_DIR}/Task+immediate.swift")

View File

@@ -27,15 +27,15 @@ function(set_if_arch_bitness var_name)
"${SIA_ARCH}" STREQUAL "powerpc")
set("${var_name}" "${SIA_CASE_32_BIT}" PARENT_SCOPE)
elseif("${SIA_ARCH}" STREQUAL "x86_64" OR
"${SIA_ARCH}" STREQUAL "amd64" OR
"${SIA_ARCH}" STREQUAL "arm64" OR
"${SIA_ARCH}" STREQUAL "arm64e" OR
"${SIA_ARCH}" STREQUAL "aarch64" OR
"${SIA_ARCH}" STREQUAL "powerpc64" OR
"${SIA_ARCH}" STREQUAL "powerpc64le" OR
"${SIA_ARCH}" STREQUAL "s390x" OR
"${SIA_ARCH}" STREQUAL "riscv64" OR
"${SIA_ARCH}" STREQUAL "wasm64")
"${SIA_ARCH}" STREQUAL "amd64" OR
"${SIA_ARCH}" STREQUAL "arm64" OR
"${SIA_ARCH}" STREQUAL "arm64e" OR
"${SIA_ARCH}" STREQUAL "aarch64" OR
"${SIA_ARCH}" STREQUAL "powerpc64" OR
"${SIA_ARCH}" STREQUAL "powerpc64le" OR
"${SIA_ARCH}" STREQUAL "s390x" OR
"${SIA_ARCH}" STREQUAL "riscv64" OR
"${SIA_ARCH}" STREQUAL "wasm64")
set("${var_name}" "${SIA_CASE_64_BIT}" PARENT_SCOPE)
else()
message(FATAL_ERROR "Unknown architecture: ${SIA_ARCH}")

View File

@@ -822,6 +822,7 @@ function(add_swift_target_library_single target name)
IS_FRAGILE)
set(SWIFTLIB_SINGLE_single_parameter_options
ARCHITECTURE
ARCHITECTURE_SUBDIR_NAME
DEPLOYMENT_VERSION_IOS
DEPLOYMENT_VERSION_OSX
DEPLOYMENT_VERSION_TVOS
@@ -888,6 +889,9 @@ function(add_swift_target_library_single target name)
precondition(SWIFTLIB_SINGLE_SDK MESSAGE "Should specify an SDK")
precondition(SWIFTLIB_SINGLE_ARCHITECTURE MESSAGE "Should specify an architecture")
precondition(SWIFTLIB_SINGLE_INSTALL_IN_COMPONENT MESSAGE "INSTALL_IN_COMPONENT is required")
if (NOT SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME)
set(SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME "${SWIFTLIB_SINGLE_ARCHITECTURE}")
endif()
if(NOT SWIFTLIB_SINGLE_SHARED AND
NOT SWIFTLIB_SINGLE_STATIC AND
@@ -903,12 +907,12 @@ function(add_swift_target_library_single target name)
# Determine the subdirectory where this library will be installed.
set(SWIFTLIB_SINGLE_SUBDIR
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE}")
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME}")
# macCatalyst ios-like builds are installed in the maccatalyst/x86_64 directory
if(maccatalyst_build_flavor STREQUAL "ios-like")
set(SWIFTLIB_SINGLE_SUBDIR
"${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE}")
"${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}/${SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME}")
endif()
if ("${SWIFTLIB_SINGLE_BOOTSTRAPPING}" STREQUAL "")
@@ -1033,6 +1037,7 @@ function(add_swift_target_library_single target name)
${SWIFTLIB_SINGLE_LINK_LIBRARIES}
SDK ${SWIFTLIB_SINGLE_SDK}
ARCHITECTURE ${SWIFTLIB_SINGLE_ARCHITECTURE}
ARCHITECTURE_SUBDIR_NAME ${SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME}
MODULE_NAME ${module_name}
MODULE_DIR ${SWIFTLIB_SINGLE_MODULE_DIR}
COMPILE_FLAGS ${SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS}
@@ -1058,9 +1063,9 @@ function(add_swift_target_library_single target name)
# If there were any swift sources, then a .swiftmodule may have been created.
# If that is the case, then add a target which is an alias of the module files.
set(VARIANT_SUFFIX "-${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE}")
set(VARIANT_SUFFIX "-${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME}")
if(maccatalyst_build_flavor STREQUAL "ios-like")
set(VARIANT_SUFFIX "-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE}")
set(VARIANT_SUFFIX "-${SWIFT_SDK_MACCATALYST_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE_SUBDIR_NAME}")
endif()
if(NOT "${SWIFTLIB_SINGLE_MODULE_TARGETS}" STREQUAL "" AND NOT "${swift_module_dependency_target}" STREQUAL "")

View File

@@ -50,7 +50,7 @@ function(handle_swift_sources
sourcesvar externalvar name)
cmake_parse_arguments(SWIFTSOURCES
"IS_MAIN;IS_STDLIB;IS_STDLIB_CORE;IS_SDK_OVERLAY;EMBED_BITCODE;STATIC;NO_LINK_NAME;IS_FRAGILE;ONLY_SWIFTMODULE;NO_SWIFTMODULE"
"SDK;ARCHITECTURE;INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS;MACCATALYST_BUILD_FLAVOR;BOOTSTRAPPING;INSTALL_BINARY_SWIFTMODULE"
"SDK;ARCHITECTURE;ARCHITECTURE_SUBDIR_NAME;INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS;MACCATALYST_BUILD_FLAVOR;BOOTSTRAPPING;INSTALL_BINARY_SWIFTMODULE"
"DEPENDS;COMPILE_FLAGS;MODULE_NAME;MODULE_DIR;ENABLE_LTO"
${ARGN})
translate_flag(${SWIFTSOURCES_IS_MAIN} "IS_MAIN" IS_MAIN_arg)
@@ -83,6 +83,9 @@ function(handle_swift_sources
precondition(SWIFTSOURCES_SDK "Should specify an SDK")
precondition(SWIFTSOURCES_ARCHITECTURE "Should specify an architecture")
precondition(SWIFTSOURCES_INSTALL_IN_COMPONENT "INSTALL_IN_COMPONENT is required")
if (NOT SWIFTSOURCES_ARCHITECTURE_SUBDIR_NAME)
set(SWIFTSOURCES_ARCHITECTURE_SUBDIR_NAME "${SWIFTSOURCES_ARCHITECTURE}")
endif()
# Clear the result variable.
set("${dependency_target_out_var_name}" "" PARENT_SCOPE)
@@ -108,12 +111,12 @@ function(handle_swift_sources
endif()
if(swift_sources)
set(objsubdir "/${SWIFTSOURCES_SDK}/${SWIFTSOURCES_ARCHITECTURE}")
set(objsubdir "/${SWIFTSOURCES_SDK}/${SWIFTSOURCES_ARCHITECTURE_SUBDIR_NAME}")
get_maccatalyst_build_flavor(maccatalyst_build_flavor
"${SWIFTSOURCES_SDK}" "${SWIFTSOURCES_MACCATALYST_BUILD_FLAVOR}")
if(maccatalyst_build_flavor STREQUAL "ios-like")
set(objsubdir "/MACCATALYST/${SWIFTSOURCES_ARCHITECTURE}")
set(objsubdir "/MACCATALYST/${SWIFTSOURCES_ARCHITECTURE_SUBDIR_NAME}")
endif()
get_bootstrapping_path(lib_dir

View File

@@ -129,7 +129,6 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
Task+TaskExecutor.swift
TaskCancellation.swift
TaskGroup.swift
TaskGroup+Embedded.swift
DiscardingTaskGroup.swift
TaskLocal.swift
TaskSleep.swift
@@ -206,6 +205,12 @@ set(LLVM_OPTIONAL_SOURCES
DispatchGlobalExecutor.cpp
)
set(SWIFT_CONCURRENCY_GYB_SOURCES
Task+init.swift.gyb
TaskGroup+addTask.swift.gyb
Task+immediate.swift.gyb
)
add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
${SWIFT_RUNTIME_CONCURRENCY_C_SOURCES}
${SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES}
@@ -214,8 +219,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
${SWIFT_RUNTIME_CONCURRENCY_NONEMBEDDED_SWIFT_SOURCES}
GYB_SOURCES
TaskGroup+addTask.swift.gyb
Task+immediate.swift.gyb
${SWIFT_CONCURRENCY_GYB_SOURCES}
SWIFT_MODULE_DEPENDS_ANDROID Android
SWIFT_MODULE_DEPENDS_LINUX Glibc
@@ -303,8 +307,10 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
endif()
set(SWIFT_SDK_embedded_THREADING_PACKAGE none)
set(SWIFT_SDK_embedded_ARCH_${arch}_MODULE "${mod}")
set(SWIFT_SDK_embedded_ARCH_${mod}_MODULE "${mod}")
set(SWIFT_SDK_embedded_LIB_SUBDIR "embedded")
set(SWIFT_SDK_embedded_ARCH_${arch}_TRIPLE "${triple}")
set(SWIFT_SDK_embedded_ARCH_${mod}_TRIPLE "${triple}")
# lib/swift/embedded/_Concurrency.swiftmodule
@@ -319,6 +325,9 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
${SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES}
${SWIFT_RUNTIME_CONCURRENCY_EMBEDDED_SWIFT_SOURCES}
GYB_SOURCES
${SWIFT_CONCURRENCY_GYB_SOURCES}
SWIFT_COMPILE_FLAGS
${extra_swift_compile_flags} -enable-experimental-feature Embedded
-parse-stdlib -DSWIFT_CONCURRENCY_EMBEDDED
@@ -328,7 +337,8 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
${extra_c_compile_flags} ${SWIFT_RUNTIME_CONCURRENCY_C_FLAGS} -DSWIFT_CONCURRENCY_EMBEDDED=1 -DSWIFT_RUNTIME_EMBEDDED=1
MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded"
SDK "embedded"
ARCHITECTURE "${mod}"
ARCHITECTURE "${arch}"
ARCHITECTURE_SUBDIR_NAME "${mod}"
DEPENDS embedded-stdlib-${mod}
INSTALL_IN_COMPONENT stdlib
)

View File

@@ -87,175 +87,6 @@ extension Task where Success == Never, Failure == Never {
}
}
@available(SwiftStdlib 5.1, *)
extension Task where Failure == Error {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public static func runDetached(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async throws -> Success
) -> Task<Success, Failure> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@discardableResult
@_alwaysEmitIntoClient
@available(*, deprecated, message: "`Task.runDetached` was replaced by `Task.detached` and will be removed shortly.")
public static func runDetached(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async throws -> Success
) -> Task<Success, Failure> {
detached(priority: priority, operation: operation)
}
#endif
}
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@_alwaysEmitIntoClient
public func detach<T>(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`detach` was replaced by `Task.detached` and will be removed shortly.")
@_alwaysEmitIntoClient
public func detach<T>(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
Task.detached(priority: priority, operation: operation)
}
#endif
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@_alwaysEmitIntoClient
public func detach<T>(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`detach` was replaced by `Task.detached` and will be removed shortly.")
@_alwaysEmitIntoClient
public func detach<T>(
priority: TaskPriority? = nil,
operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
Task.detached(priority: priority, operation: operation)
}
#endif
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@_alwaysEmitIntoClient
public func asyncDetached<T>(
priority: TaskPriority? = nil,
@_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`asyncDetached` was replaced by `Task.detached` and will be removed shortly.")
@_alwaysEmitIntoClient
public func asyncDetached<T>(
priority: TaskPriority? = nil,
@_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
return Task.detached(priority: priority, operation: operation)
}
#endif
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@_alwaysEmitIntoClient
public func asyncDetached<T>(
priority: TaskPriority? = nil,
@_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@discardableResult
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`asyncDetached` was replaced by `Task.detached` and will be removed shortly.")
@_alwaysEmitIntoClient
public func asyncDetached<T>(
priority: TaskPriority? = nil,
@_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
return Task.detached(priority: priority, operation: operation)
}
#endif
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@discardableResult
@_alwaysEmitIntoClient
public func async<T>(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`async` was replaced by `Task.init` and will be removed shortly.")
@discardableResult
@_alwaysEmitIntoClient
public func async<T>(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T
) -> Task<T, Never> {
.init(priority: priority, operation: operation)
}
#endif
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@available(SwiftStdlib 5.1, *)
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
@discardableResult
@_alwaysEmitIntoClient
public func async<T>(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
@available(SwiftStdlib 5.1, *)
@available(*, deprecated, message: "`async` was replaced by `Task.init` and will be removed shortly.")
@discardableResult
@_alwaysEmitIntoClient
public func async<T>(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T
) -> Task<T, Error> {
.init(priority: priority, operation: operation)
}
#endif
@available(SwiftStdlib 5.1, *)
extension Task where Success == Never, Failure == Never {
@available(*, deprecated, message: "`Task.Group` was replaced by `ThrowingTaskGroup` and `TaskGroup` and will be removed shortly.")

View File

@@ -187,263 +187,6 @@ public func _unsafeInheritExecutor_withTaskExecutorPreference<T: Sendable>(
return try await operation()
}
/// Task with specified executor -----------------------------------------------
@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension Task where Failure == Never {
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// This overload allows specifying a preferred ``TaskExecutor`` on which
/// the `operation`, as well as all child tasks created from this task will be
/// executing whenever possible. Refer to ``TaskExecutor`` for a detailed discussion
/// of the effect of task executors on execution semantics of asynchronous code.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `Task.detached(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - taskExecutor: the preferred task executor for this task,
/// and any child tasks created by it. Explicitly passing `nil` is
/// interpreted as "no preference".
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
/// - SeeAlso: ``withTaskExecutorPreference(_:operation:)``
@discardableResult
@_alwaysEmitIntoClient
public init(
executorPreference taskExecutor: consuming (any TaskExecutor)?,
priority: TaskPriority? = nil,
operation: sending @escaping () async -> Success
) {
guard let taskExecutor else {
self = Self.init(priority: priority, operation: operation)
return
}
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
let (task, _) = Builtin.createTask(
flags: flags,
initialTaskExecutorConsuming: taskExecutor,
operation: operation)
#else
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
let (task, _) = Builtin.createAsyncTaskWithExecutor(
flags, executorBuiltin, operation)
#endif
self._task = task
}
}
@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension Task where Failure == Error {
/// Runs the given throwing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `detach(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - taskExecutor: the preferred task executor for this task,
/// and any child tasks created by it. Explicitly passing `nil` is
/// interpreted as "no preference".
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
/// - SeeAlso: ``withTaskExecutorPreference(_:operation:)``
@discardableResult
@_alwaysEmitIntoClient
public init(
executorPreference taskExecutor: consuming (any TaskExecutor)?,
priority: TaskPriority? = nil,
operation: sending @escaping () async throws -> Success
) {
guard let taskExecutor else {
self = Self.init(priority: priority, operation: operation)
return
}
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
let (task, _) = Builtin.createTask(
flags: flags,
initialTaskExecutorConsuming: taskExecutor,
operation: operation)
#else
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
let (task, _) = Builtin.createAsyncTaskWithExecutor(
flags, executorBuiltin, operation)
#endif
self._task = task
}
}
// ==== Detached tasks ---------------------------------------------------------
@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension Task where Failure == Never {
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - taskExecutor: the preferred task executor for this task,
/// and any child tasks created by it. Explicitly passing `nil` is
/// interpreted as "no preference".
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
/// - Returns: A reference to the newly created task.
/// - SeeAlso: ``withTaskExecutorPreference(_:operation:)``
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
executorPreference taskExecutor: (any TaskExecutor)?,
priority: TaskPriority? = nil,
operation: sending @escaping () async -> Success
) -> Task<Success, Failure> {
guard let taskExecutor else {
return Self.detached(priority: priority, operation: operation)
}
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
let (task, _) = Builtin.createTask(
flags: flags,
initialTaskExecutorConsuming: taskExecutor,
operation: operation)
#else
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
let (task, _) = Builtin.createAsyncTaskWithExecutor(
flags, executorBuiltin, operation)
#endif
return Task(task)
}
}
@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension Task where Failure == Error {
/// Runs the given throwing operation asynchronously
/// as part of a new top-level task.
///
/// If the operation throws an error, this method propagates that error.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - taskExecutor: the preferred task executor for this task,
/// and any child tasks created by it. Explicitly passing `nil` is
/// interpreted as "no preference".
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
/// - Returns: A reference to the newly created task.
/// - SeeAlso: ``withTaskExecutorPreference(_:operation:)``
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
executorPreference taskExecutor: (any TaskExecutor)?,
priority: TaskPriority? = nil,
operation: sending @escaping () async throws -> Success
) -> Task<Success, Failure> {
guard let taskExecutor else {
return Self.detached(priority: priority, operation: operation)
}
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
let (task, _) = Builtin.createTask(
flags: flags,
initialTaskExecutorConsuming: taskExecutor,
operation: operation)
#else
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
let (task, _) = Builtin.createAsyncTaskWithExecutor(
flags, executorBuiltin, operation)
#endif
return Task(task)
}
}
// ==== Unsafe Current Task ----------------------------------------------------
@available(SwiftStdlib 6.0, *)
@_unavailableInEmbedded
extension UnsafeCurrentTask {

View File

@@ -0,0 +1,415 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Swift
% for (METHOD_VARIANTS, ALL_AVAILABILITY, PARAMS) in [
% # ==== -------------------------------------------------------------------------------------------------------------
% # ==== Without task executor, but available ever since 5.1
% ([ # METHOD_VARIANT
% 'init',
% 'init/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% ],
% [ # PARAMS
% 'name: String? = nil',
% 'priority: TaskPriority? = nil',
% '@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success',
% ]),
% # ==== --------------------------------------------------------------------
% ([ # METHOD_VARIANT
% 'static func detached',
% 'static func detached/*throws*/',
% ],
% [
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% ],
% [ # PARAMS
% 'name: String? = nil',
% 'priority: TaskPriority? = nil',
% 'operation: sending @escaping @isolated(any) () async throws -> Success',
% ]),
% # ==== -------------------------------------------------------------------------------------------------------------
% # ==== With task executor, but available only since 6.0
% ([ # METHOD_VARIANT
% 'init',
% 'init/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 6.0, *)',
% ],
% [ # PARAMS
% 'name: String? = nil',
% 'executorPreference taskExecutor: (any TaskExecutor)?',
% 'priority: TaskPriority? = nil',
% 'operation: sending @escaping () async throws -> Success',
% ]),
% # ==== --------------------------------------------------------------------
% ([ # METHOD_VARIANT
% 'static func detached',
% 'static func detached/*throws*/',
% ],
% [
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 6.0, *)',
% ],
% [ # PARAMS
% 'name: String? = nil',
% 'executorPreference taskExecutor: (any TaskExecutor)?',
% 'priority: TaskPriority? = nil',
% 'operation: sending @escaping () async throws -> Success',
% ]),
% # !!!! -------------------------------------------------------------------------------------------------------------
% # !!!! Legacy / Source Compatibility "Shims"
% # !!!!
% # !!!! These legacy APIs technically did not have @isolated(any) but since they're all emit-into-client,
% # !!!! we just allow them to become slightly better here. It makes source generation simpler, and doesn't really hurt.
% # !!!! -------------------------------------------------------------------------------------------------------------
% # ==== Legacy API: Global 'detach' function
% ([ # METHOD_VARIANT
% 'func detach<Success>',
% 'func detach<Success>/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% '@available(*, deprecated, message: "`detach` was replaced by `Task.detached` and will be removed shortly.")',
% ],
% [ # PARAMS
% 'priority: TaskPriority? = nil',
% '@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping @isolated(any) () async throws -> Success',
% ]),
% # ==== Legacy API: runDetached
% ([ # METHOD_VARIANT
% 'static func runDetached',
% 'static func runDetached/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% '@available(*, deprecated, message: "`Task.runDetached` was replaced by `Task.detached` and will be removed shortly.")',
% ],
% [ # PARAMS
% 'priority: TaskPriority? = nil',
% '@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping @isolated(any) () async throws -> Success',
% ]),
% # ==== Legacy API: asyncDetached
% ([ # METHOD_VARIANT
% 'func asyncDetached<Success>',
% 'func asyncDetached<Success>/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% '@available(*, deprecated, message: "`asyncDetached` was replaced by `Task.detached` and will be removed shortly.")',
% ],
% [ # PARAMS
% 'priority: TaskPriority? = nil',
% '@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping @isolated(any) () async throws -> Success',
% ]),
% # ==== Legacy API: async
% ([ # METHOD_VARIANT
% 'func async<Success>',
% 'func async<Success>/*throws*/',
% ],
% [ # ALL_AVAILABILITY
% '@_alwaysEmitIntoClient',
% '@available(SwiftStdlib 5.1, *)',
% '@available(*, deprecated, message: "`async` was replaced by `Task.init` and will be removed shortly.")',
% ],
% [ # PARAMS
% 'priority: TaskPriority? = nil',
% '@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping @isolated(any) () async throws -> Success',
% ]),
% ]:
% for METHOD_VARIANT in METHOD_VARIANTS:
% IS_TOP_LEVEL_FUNC = (not ('init' in METHOD_VARIANT)) and (not ('static' in METHOD_VARIANT))
% IS_INIT = 'init' in METHOD_VARIANT
% IS_DETACHED = 'detach' in METHOD_VARIANT.lower()
% IS_THROWING = 'throws' in METHOD_VARIANT
%
% HAS_TASK_PRIORITY = any('priority:' in param for param in PARAMS)
% HAS_TASK_NAME = any('name:' in param for param in PARAMS)
% HAS_TASK_EXECUTOR = any('taskExecutor:' in param for param in PARAMS)
% HAS_ISOLATED_ANY = any('@isolated(any)' in param for param in PARAMS)
% IS_DEPRECATED = any('deprecated' in a for a in ALL_AVAILABILITY)
%
% if IS_THROWING:
% FAILURE_TYPE = 'Error'
% else:
% FAILURE_TYPE = 'Never'
% end
%{
def adjust_params_for_kind(params):
res = []
for p in params:
np = p
if not IS_THROWING:
np = np.replace("throws", "")
res.append(np)
return res
def adjust_availability(avails):
res = []
for av in avails:
adjusted = av
if HAS_TASK_EXECUTOR:
adjusted = adjusted.replace("SwiftStdlib 5.1", "SwiftStdlib 6.0")
res.append(adjusted)
return res
if IS_INIT:
ARROW_RETURN_TYPE = '' # init does not spell out return type
else:
ARROW_RETURN_TYPE = f'-> Task<Success, {FAILURE_TYPE}>'
}%
% # ====================================================================================================================
% if not IS_TOP_LEVEL_FUNC:
extension Task where Failure == ${FAILURE_TYPE} {
% end
% # --------------------------------------------------------------------------------------------------------------------
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public ${METHOD_VARIANT}(
${",\n ".join(adjust_params_for_kind(PARAMS))}
) ${ARROW_RETURN_TYPE}{
fatalError("Unavailable in task-to-thread concurrency model.")
}
% # --------------------------------------------------------------------------------------------------------------------
% if not HAS_TASK_EXECUTOR:
#elseif $Embedded
@discardableResult
@_alwaysEmitIntoClient
${" \n".join(adjust_availability(['@available(SwiftStdlib 5.1, *)']))}
public ${METHOD_VARIANT}(
${",\n ".join(adjust_params_for_kind(PARAMS))}
) ${ARROW_RETURN_TYPE}{
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority,
isChildTask: false,
copyTaskLocals: ${'true' if not IS_DETACHED else 'false /* detached */'},
inheritContext: true,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false,
isSynchronousStart: false)
let (task, _) = Builtin.createAsyncTask(flags, operation)
% if IS_INIT:
self._task = task
% else:
return Task(task)
% end
}
% end # not HAS_TASK_EXECUTOR
% # --------------------------------------------------------------------------------------------------------------------
#else
% if IS_DEPRECATED:
/// Deprecated, available only for source compatibility reasons.
% else:
% # We skip documentation for the legacy APIs which are just here for source compatibility reasons.
% if IS_THROWING:
/// Runs the given throwing operation asynchronously
% else:
/// Runs the given nonthrowing operation asynchronously
% end
% if IS_DETACHED:
/// as part of a new _unstructured_ _detached_ top-level task.
% else:
/// as part of a new _unstructured_ top-level task.
% end
///
% if IS_THROWING:
/// If the `operation` throws an error, it is caught by the `Task` and will be
/// rethrown only when the task's `value` is awaited. Take care to not accidentally
/// dismiss errors by not awaiting on the task's resulting value.
% end
///
% if IS_DETACHED:
/// Don't use a detached unstructured task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
% end
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
% if HAS_TASK_NAME:
/// - name: Human readable name of the task.
% end
% if HAS_TASK_EXECUTOR:
/// - taskExecutor: The task executor that the child task should be started on and keep using.
/// Explicitly passing `nil` as the executor preference is equivalent to no preference,
/// and effectively means to inherit the outer context's executor preference.
/// You can also pass the ``globalConcurrentExecutor`` global executor explicitly.
% end
/// - priority: The priority of the operation task.
% if IS_DETACHED:
/// Omit this parameter or pass `nil` to inherit the enclosing context's base priority.
% end
/// - operation: The operation to perform.
///
/// - Returns: A reference to the task.
% end # IS_DEPRECATED
${"\n ".join(adjust_availability(ALL_AVAILABILITY))}
@discardableResult
public ${METHOD_VARIANT}( // Task ${METHOD_VARIANT}
${",\n ".join(adjust_params_for_kind(PARAMS))}
) ${ARROW_RETURN_TYPE}{
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority,
isChildTask: false,
copyTaskLocals: ${'true' if not IS_DETACHED else 'false'},
inheritContext: ${'true' if not IS_DETACHED else 'false'},
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false,
isSynchronousStart: false)
% if HAS_ISOLATED_ANY:
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
% end # HAS_ISOLATED_ANY
var task: Builtin.NativeObject?
% if HAS_TASK_NAME:
#if $BuiltinCreateAsyncTaskName
if let name {
% if HAS_TASK_EXECUTOR:
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
% if HAS_TASK_EXECUTOR:
initialTaskExecutorConsuming: taskExecutor,
% end
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
#else // no $BuiltinCreateAsyncTaskOwnedTaskExecutor
// legacy branch for the non-consuming task executor
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
initialTaskExecutor: executorBuiltin,
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
#endif // $BuiltinCreateAsyncTaskOwnedTaskExecutor
% else: # if no TASK_EXECUTOR
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
% end # if no HAS_TASK_EXECUTOR
} // let name
#endif // $BuiltinCreateAsyncTaskName
% end # HAS_TASK_NAME
% if HAS_TASK_EXECUTOR:
// Task name was not set, or task name createTask is unavailable
if task == nil {
assert(name == nil)
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
task = Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
initialTaskExecutorConsuming: taskExecutor,
operation: operation).0
#else
// legacy branch for the non-consuming task executor
let executorBuiltin: Builtin.Executor =
taskExecutor.asUnownedTaskExecutor().executor
task = Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
initialTaskExecutor: executorBuiltin,
operation: operation).0
#endif
}
% end # HAS_TASK_EXECUTOR
if task == nil {
// either no task name was set, or names are unsupported
task = Builtin.createTask(
flags: flags,
% if HAS_ISOLATED_ANY:
initialSerialExecutor: builtinSerialExecutor,
% end
operation: operation).0
}
% if IS_INIT:
self._task = task!
% else:
return Task(task!)
% end
}
#endif
% if not IS_TOP_LEVEL_FUNC:
} // extension Task ...
% end
% end
% end
// =====================================================================================================================
// =====================================================================================================================

View File

@@ -580,630 +580,6 @@ func taskCreateFlags(
return bits
}
// ==== Task Creation ----------------------------------------------------------
@available(SwiftStdlib 5.1, *)
extension Task where Failure == Never {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public init(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async -> Success
) {
fatalError("Unavailable in task-to-thread concurrency model.")
}
#else
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `Task.detached(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
@discardableResult
@_alwaysEmitIntoClient
public init(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async -> Success
) {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
let (task, _) = Builtin.createTask(flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation)
self._task = task
}
#endif
}
@available(SwiftStdlib 6.2, *)
extension Task where Failure == Never {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public init(
name: String?,
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async -> Success
) {
fatalError("Unavailable in task-to-thread concurrency model.")
}
#elseif $Embedded
@discardableResult
@_alwaysEmitIntoClient
@available(SwiftStdlib 6.2, *)
public init(
name: String?,
// TaskExecutor is unavailable in embedded
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping () async -> Success
) {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority,
isChildTask: false,
copyTaskLocals: true,
inheritContext: true,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false,
isSynchronousStart: false)
// Create the asynchronous task.
let (task, _) = Builtin.createAsyncTask(flags, operation)
self._task = task
}
#else
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `Task.detached(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - name: The high-level human-readable name given for this task
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
@discardableResult
@_alwaysEmitIntoClient
@available(SwiftStdlib 6.2, *)
public init(
name: String?,
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async -> Success
) {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
var task: Builtin.NativeObject?
#if $BuiltinCreateAsyncTaskName
if let name {
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
}
#endif
if task == nil {
// either no task name was set, or names are unsupported
task = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation).0
}
self._task = task!
}
#endif
}
@available(SwiftStdlib 5.1, *)
extension Task where Failure == Error {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public init(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success
) {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
/// Runs the given throwing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `detach(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
@discardableResult
@_alwaysEmitIntoClient
public init(
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success
) {
// Set up the task flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task future.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
let (task, _) = Builtin.createTask(flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation)
self._task = task
}
#endif
}
@available(SwiftStdlib 6.2, *)
extension Task where Failure == Error {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public init(
name: String?,
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success
) {
fatalError("Unavailable in task-to-thread concurrency model.")
}
#elseif $Embedded
@discardableResult
@_alwaysEmitIntoClient
@available(SwiftStdlib 6.2, *)
public init(
name: String?,
// TaskExecutor is unavailable in embedded
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping () async throws -> Success
) {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task.
let (task, _) = Builtin.createAsyncTask(flags, operation)
self._task = task
}
#else
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task on behalf of the current actor.
///
/// Use this function when creating asynchronous work
/// that operates on behalf of the synchronous function that calls it.
/// Like `Task.detached(priority:operation:)`,
/// this function creates a separate, top-level task.
/// Unlike `Task.detached(priority:operation:)`,
/// the task created by `Task.init(priority:operation:)`
/// inherits the priority and actor context of the caller,
/// so the operation is treated more like an asynchronous extension
/// to the synchronous operation.
///
/// You need to keep a reference to the task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - name: The high-level human-readable name given for this task
/// - priority: The priority of the task.
/// Pass `nil` to use the priority from `Task.currentPriority`.
/// - operation: The operation to perform.
@discardableResult
@_alwaysEmitIntoClient
@available(SwiftStdlib 6.2, *)
public init(
name: String?,
priority: TaskPriority? = nil,
@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success
) {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: true,
inheritContext: true, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
var task: Builtin.NativeObject?
#if $BuiltinCreateAsyncTaskName
if let name {
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
}
#endif
if task == nil {
// either no task name was set, or names are unsupported
task = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation).0
}
self._task = task!
}
#endif
}
// ==== Detached Tasks ---------------------------------------------------------
@available(SwiftStdlib 5.1, *)
extension Task where Failure == Never {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public static func detached(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Success
) -> Task<Success, Failure> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - priority: The priority of the task.
/// - operation: The operation to perform.
///
/// - Returns: A reference to the task.
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Success
) -> Task<Success, Failure> {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task future.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
let (task, _) = Builtin.createTask(flags: flags,
initialSerialExecutor:
builtinSerialExecutor,
operation: operation)
return Task(task)
}
#endif
}
@available(SwiftStdlib 6.2, *)
extension Task where Failure == Never {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public static func detached(
name: String?,
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Success
) -> Task<Success, Failure> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
/// Runs the given nonthrowing operation asynchronously
/// as part of a new top-level task.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - name: Human readable name of the task.
/// - priority: The priority of the task.
/// - operation: The operation to perform.
///
/// - Returns: A reference to the task.
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
name: String?,
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Success
) -> Task<Success, Failure> {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
var task: Builtin.NativeObject?
#if $BuiltinCreateAsyncTaskName
if let name {
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
}
#endif
if task == nil {
// either no task name was set, or names are unsupported
task = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation).0
}
return Task(task!)
}
#endif
}
@available(SwiftStdlib 5.1, *)
extension Task where Failure == Error {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public static func detached(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Success
) -> Task<Success, Failure> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
/// Runs the given throwing operation asynchronously
/// as part of a new top-level task.
///
/// If the operation throws an error, this method propagates that error.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - priority: The priority of the task.
/// - operation: The operation to perform.
///
/// - Returns: A reference to the task.
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Success
) -> Task<Success, Failure> {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task future.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
let (task, _) = Builtin.createTask(flags: flags,
initialSerialExecutor:
builtinSerialExecutor,
operation: operation)
return Task(task)
}
#endif
}
@available(SwiftStdlib 6.2, *)
extension Task where Failure == Error {
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@discardableResult
@_alwaysEmitIntoClient
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
public static func detached(
name: String?,
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Success
) -> Task<Success, Failure> {
fatalError("Unavailable in task-to-thread concurrency model")
}
#else
/// Runs the given throwing operation asynchronously
/// as part of a new top-level task.
///
/// If the operation throws an error, this method propagates that error.
///
/// Don't use a detached task if it's possible
/// to model the operation using structured concurrency features like child tasks.
/// Child tasks inherit the parent task's priority and task-local storage,
/// and canceling a parent task automatically cancels all of its child tasks.
/// You need to handle these considerations manually with a detached task.
///
/// You need to keep a reference to the detached task
/// if you want to cancel it by calling the `Task.cancel()` method.
/// Discarding your reference to a detached task
/// doesn't implicitly cancel that task,
/// it only makes it impossible for you to explicitly cancel the task.
///
/// - Parameters:
/// - priority: The priority of the task.
/// - operation: The operation to perform.
///
/// - Returns: A reference to the task.
@discardableResult
@_alwaysEmitIntoClient
public static func detached(
name: String?,
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Success
) -> Task<Success, Failure> {
// Set up the job flags for a new task.
let flags = taskCreateFlags(
priority: priority, isChildTask: false, copyTaskLocals: false,
inheritContext: false, enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: false, isSynchronousStart: false)
// Create the asynchronous task future.
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
var task: Builtin.NativeObject?
#if $BuiltinCreateAsyncTaskName
if let name {
task =
unsafe name.utf8CString.withUnsafeBufferPointer { nameBytes in
Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
}
#endif
if task == nil {
// either no task name was set, or names are unsupported
task = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
operation: operation).0
}
return Task(task!)
}
#endif
}
// ==== Task Name --------------------------------------------------------------
@available(SwiftStdlib 6.2, *)
@@ -1224,6 +600,13 @@ extension Task where Success == Never, Failure == Never {
/// }
/// }
/// }
///
/// ### Task name availability
/// The task name is only available when running with a recent runtime (Swift 6.2+).
///
/// ``Task`` initializers which may accept a task name are more available than this property,
/// for convenience purposes, in order to not have to set task names conditionally
/// however their effect is runtime dependent, and is reflected in the availability of this property.
@available(SwiftStdlib 6.2, *)
public static var name: String? {
return _getCurrentTaskNameString()

View File

@@ -1,283 +0,0 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Swift
// FIXME: This is a workaround for trouble including gyb-generated sources
#if SWIFT_CONCURRENCY_EMBEDDED
@available(SwiftStdlib 5.1, *)
extension TaskGroup {
@available(SwiftStdlib 5.1, *)
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> ChildTaskResult
) {
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: true,
isDiscardingTask: false,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
}
@available(SwiftStdlib 5.1, *)
@_alwaysEmitIntoClient
public mutating func addTaskUnlessCancelled(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> ChildTaskResult
) -> Bool {
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
guard canAdd else {
return false
}
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
return true
}
}
@available(SwiftStdlib 5.1, *)
extension ThrowingTaskGroup {
@available(SwiftStdlib 5.1, *)
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
) {
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: true,
isDiscardingTask: false,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
}
@available(SwiftStdlib 5.1, *)
@_alwaysEmitIntoClient
public mutating func addTaskUnlessCancelled(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult
) -> Bool {
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
guard canAdd else {
return false
}
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
return true
}
}
@available(SwiftStdlib 5.9, *)
extension DiscardingTaskGroup {
@available(SwiftStdlib 5.9, *)
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Void
) {
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: true,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
}
@available(SwiftStdlib 5.9, *)
@_alwaysEmitIntoClient
public mutating func addTaskUnlessCancelled(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async -> Void
) -> Bool {
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
guard canAdd else {
return false
}
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
return true
}
}
@available(SwiftStdlib 5.9, *)
extension ThrowingDiscardingTaskGroup {
@available(SwiftStdlib 5.9, *)
@_alwaysEmitIntoClient
public mutating func addTask(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Void
) {
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: true,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
}
@available(SwiftStdlib 5.9, *)
@_alwaysEmitIntoClient
public mutating func addTaskUnlessCancelled(
priority: TaskPriority? = nil,
operation: sending @escaping @isolated(any) () async throws -> Void
) -> Bool {
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
guard canAdd else {
return false
}
let flags = taskCreateFlags(
priority: priority,
isChildTask: true,
copyTaskLocals: false,
inheritContext: false,
enqueueJob: true,
addPendingGroupTaskUnconditionally: false,
isDiscardingTask: true,
isSynchronousStart: false
)
let builtinSerialExecutor =
unsafe Builtin.extractFunctionIsolation(operation)?.unownedExecutor.executor
_ = Builtin.createTask(
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
operation: operation).0
return true
}
}
#endif

View File

@@ -31,7 +31,7 @@ import Swift
% 'ThrowingDiscardingTaskGroup'
% ],
% [
% '@available(SwiftStdlib 6.2, *)',
% '@available(SwiftStdlib 6.0, *)', # because task executor
% '@_unavailableInEmbedded', # since TaskExecutor is not available on embedded
% ],
% ['addTask', 'addTaskUnlessCancelled'],
@@ -43,6 +43,42 @@ import Swift
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
% ],
% ),
% (
% '', # no #if condition
% [
% 'TaskGroup',
% 'ThrowingTaskGroup',
% ],
% [
% '@available(SwiftStdlib 5.1, *)',
% ],
% ['addTask', 'addTaskUnlessCancelled'],
% [
% 'name: String?',
% # without task executor
% 'priority: TaskPriority? = nil',
% # throws and ChildTaskResult will be adjusted per task group type
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
% ],
% ),
% (
% '', # no #if condition
% [
% 'DiscardingTaskGroup',
% 'ThrowingDiscardingTaskGroup'
% ],
% [
% '@available(SwiftStdlib 5.9, *)', # because Discarding task groups
% ],
% ['addTask', 'addTaskUnlessCancelled'],
% [
% 'name: String?',
% # without task executor
% 'priority: TaskPriority? = nil',
% # throws and ChildTaskResult will be adjusted per task group type
% 'operation: sending @escaping @isolated(any) () async throws -> ChildTaskResult'
% ],
% ),
% # -----------------------------------------------------------------------
% # === Added TaskExecutor
% (
@@ -170,7 +206,9 @@ import Swift
#if ${IFDEF}
% end
% if IS_DISCARDING:
% if HAS_TASK_EXECUTOR:
@available(SwiftStdlib 6.0, *)
% elif IS_DISCARDING:
@available(SwiftStdlib 5.9, *)
% else:
@available(SwiftStdlib 5.1, *)
@@ -267,7 +305,9 @@ extension ${TYPE} {
flags: flags,
initialSerialExecutor: builtinSerialExecutor,
taskGroup: _group,
% if HAS_TASK_EXECUTOR:
initialTaskExecutorConsuming: taskExecutor,
% end
taskName: nameBytes.baseAddress!._rawValue,
operation: operation).0
}
@@ -275,8 +315,8 @@ extension ${TYPE} {
#endif // $BuiltinCreateAsyncTaskName
% end # HAS_TASK_NAME
// Task name was not set, or task name createTask is unavailable
% if HAS_TASK_EXECUTOR:
// Task name was not set, or task name createTask is unavailable
if task == nil, let taskExecutor {
#if $BuiltinCreateAsyncTaskOwnedTaskExecutor
task = ${TASK_CREATE_FN}(

View File

@@ -0,0 +1,73 @@
// RUN: %target-swift-frontend -emit-sil -verify -o /dev/null -verify %s
struct Boom: Error {}
@available(SwiftStdlib 6.2, *)
func testName() {
_ = Task.name
}
@available(SwiftStdlib 6.0, *)
func taskExecutor() async {
Task(name: "name", executorPreference: nil) { }
Task(name: "name", executorPreference: nil) { throw Boom() }
Task.detached(name: "name", executorPreference: nil) { throw Boom() }
await withTaskGroup(of: Void.self) { group in
group.addTask(name: "name", executorPreference: nil) {
()
}
}
await withThrowingTaskGroup(of: Void.self) { group in
group.addTask(name: "name", executorPreference: nil) {
()
}
}
await withDiscardingTaskGroup { group in
group.addTask(name: "name", executorPreference: nil) {
()
}
}
try! await withThrowingDiscardingTaskGroup { group in
group.addTask(name: "name", executorPreference: nil) {
()
}
}
}
@available(SwiftStdlib 5.1, *)
func backDeployedNames() async {
Task(name: "name") { }
Task(name: "name") { throw Boom() }
Task.detached(name: "name") { }
Task.detached(name: "name") { throw Boom() }
await withTaskGroup(of: Void.self) { group in
group.addTask(name: "name") {
()
}
}
await withThrowingTaskGroup(of: Void.self) { group in
group.addTask(name: "name") {
()
}
}
}
@available(SwiftStdlib 5.9, *)
func backDeployedDiscarding() async {
await withDiscardingTaskGroup { group in
group.addTask(name: "name") {
()
}
}
try! await withThrowingDiscardingTaskGroup { group in
group.addTask(name: "name") {
()
}
}
}

View File

@@ -1767,7 +1767,7 @@ extension MyActor {
_ = sc
Task { // expected-tns-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(priority:operation:)' risks causing races in between local and caller code}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code}}
_ = sc
}
@@ -1975,7 +1975,7 @@ func mutableLocalCaptureDataRace() async {
_ = x
Task.detached { x = 1 } // expected-tns-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to static method 'detached(priority:operation:)' risks causing races in between local and caller code}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to static method 'detached(name:priority:operation:)' risks causing races in between local and caller code}}
x = 2 // expected-tns-note {{access can happen concurrently}}
}
@@ -1985,7 +1985,7 @@ func mutableLocalCaptureDataRace2() async {
x = 0
Task.detached { x = 1 } // expected-tns-warning {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to static method 'detached(priority:operation:)' risks causing races in between local and caller code}}
// expected-tns-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to static method 'detached(name:priority:operation:)' risks causing races in between local and caller code}}
print(x) // expected-tns-note {{access can happen concurrently}}
}

View File

@@ -60,7 +60,7 @@ extension MyActor {
_ = sc
Task { // expected-error {{sending value of non-Sendable type '() async -> ()' risks causing data races}}
// expected-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(priority:operation:)' risks causing races in between local and caller code}}
// expected-note @-1 {{Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code}}
_ = sc
}

View File

@@ -167,6 +167,9 @@ class WasmStdlib(cmake_product.CMakeProduct):
self.cmake_options.define('SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB:BOOL', 'TRUE')
self.cmake_options.define(
'SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB_CROSS_COMPILING', 'TRUE')
self.cmake_options.define(
'SWIFT_SDK_embedded_ARCH_wasm32_PATH:PATH',
self._wasi_sysroot_path("wasm32-wasi"))
self.cmake_options.define(
'SWIFT_SDK_embedded_ARCH_wasm32-unknown-wasip1_PATH:PATH',
self._wasi_sysroot_path("wasm32-wasi"))