From cc5c4eeac52d51941792b873fb2cf51009df072c Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 25 Apr 2025 10:34:36 -0700 Subject: [PATCH 1/3] [embedded] Make the CMake setup for Embedded Concurrency distnguish ARCH and SUBDIR for builds products --- stdlib/cmake/modules/AddSwiftStdlib.cmake | 13 +++++++++---- stdlib/cmake/modules/SwiftSource.cmake | 9 ++++++--- stdlib/public/Concurrency/CMakeLists.txt | 5 ++++- .../swift_build_support/products/wasmstdlib.py | 3 +++ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index 28829186bc4e4..ce113989ad75d 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -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 "") diff --git a/stdlib/cmake/modules/SwiftSource.cmake b/stdlib/cmake/modules/SwiftSource.cmake index b9f45730c5feb..c834047478bdb 100644 --- a/stdlib/cmake/modules/SwiftSource.cmake +++ b/stdlib/cmake/modules/SwiftSource.cmake @@ -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 diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index fb8742b391bac..d0fc73ee3e524 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -295,8 +295,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 @@ -320,7 +322,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 ) diff --git a/utils/swift_build_support/swift_build_support/products/wasmstdlib.py b/utils/swift_build_support/swift_build_support/products/wasmstdlib.py index 9cf73d3396d1d..c1fa73fad3d4c 100644 --- a/utils/swift_build_support/swift_build_support/products/wasmstdlib.py +++ b/utils/swift_build_support/swift_build_support/products/wasmstdlib.py @@ -167,6 +167,9 @@ def _build_stdlib(self, host_target, target_triple, llvm_cmake_dir): 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")) From 42811f9734e9f42a9395f2aa8913b5dc52fd50ee Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Tue, 22 Apr 2025 19:59:18 +0900 Subject: [PATCH 2/3] [Concurrency] Update how we add parameters to Task.init, change the AEIC funcs [Concurrency] Lower availability for task names + addTask WIP on changing the always emit into client funcs --- Runtimes/Core/Concurrency/CMakeLists.txt | 1 + stdlib/public/Concurrency/CMakeLists.txt | 1 + .../SourceCompatibilityShims.swift | 373 +++++------ .../Concurrency/Task+TaskExecutor.swift | 257 ------- stdlib/public/Concurrency/Task+init.swift.gyb | 331 +++++++++ stdlib/public/Concurrency/Task.swift | 632 +----------------- .../Concurrency/TaskGroup+addTask.swift.gyb | 44 +- .../task_naming_availability.swift | 73 ++ 8 files changed, 642 insertions(+), 1070 deletions(-) create mode 100644 stdlib/public/Concurrency/Task+init.swift.gyb create mode 100644 test/Concurrency/task_naming_availability.swift diff --git a/Runtimes/Core/Concurrency/CMakeLists.txt b/Runtimes/Core/Concurrency/CMakeLists.txt index 8dd89783d7ac2..dee49245fcb87 100644 --- a/Runtimes/Core/Concurrency/CMakeLists.txt +++ b/Runtimes/Core/Concurrency/CMakeLists.txt @@ -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+startSynchronously.swift.gyb Task+startSynchronously.swift) diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index d0fc73ee3e524..1ccddee164eac 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -206,6 +206,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I ${SWIFT_RUNTIME_CONCURRENCY_NONEMBEDDED_SWIFT_SOURCES} GYB_SOURCES + Task+init.swift.gyb TaskGroup+addTask.swift.gyb Task+startSynchronously.swift.gyb diff --git a/stdlib/public/Concurrency/SourceCompatibilityShims.swift b/stdlib/public/Concurrency/SourceCompatibilityShims.swift index 75242f0421b1f..b63e84c795131 100644 --- a/stdlib/public/Concurrency/SourceCompatibilityShims.swift +++ b/stdlib/public/Concurrency/SourceCompatibilityShims.swift @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// import Swift +import _Concurrency @available(SwiftStdlib 5.1, *) extension Task where Success == Never, Failure == Never { @@ -87,192 +88,192 @@ 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 { - 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 { - 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( - priority: TaskPriority? = nil, - operation: __owned @Sendable @escaping () async -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - operation: __owned @Sendable @escaping () async -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -) -> Task { - .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( - priority: TaskPriority? = nil, - @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - 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( - priority: TaskPriority? = nil, - @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -) -> Task { - .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.") - public typealias Group = ThrowingTaskGroup - - @available(*, deprecated, message: "`Task.withGroup` was replaced by `withThrowingTaskGroup` and `withTaskGroup` and will be removed shortly.") - @_alwaysEmitIntoClient - public static func withGroup( - resultType: TaskResult.Type, - returning returnType: BodyResult.Type = BodyResult.self, - body: (inout Task.Group) async throws -> BodyResult - ) async rethrows -> BodyResult { - try await withThrowingTaskGroup(of: resultType) { group in - try await body(&group) - } - } -} +//@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 { +// 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 { +// 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( +// priority: TaskPriority? = nil, +// operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T +//) -> Task { +// .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( +// priority: TaskPriority? = nil, +// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// 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( +// priority: TaskPriority? = nil, +// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T +//) -> Task { +// .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.") +// public typealias Group = ThrowingTaskGroup +// +// @available(*, deprecated, message: "`Task.withGroup` was replaced by `withThrowingTaskGroup` and `withTaskGroup` and will be removed shortly.") +// @_alwaysEmitIntoClient +// public static func withGroup( +// resultType: TaskResult.Type, +// returning returnType: BodyResult.Type = BodyResult.self, +// body: (inout Task.Group) async throws -> BodyResult +// ) async rethrows -> BodyResult { +// try await withThrowingTaskGroup(of: resultType) { group in +// try await body(&group) +// } +// } +//} @available(SwiftStdlib 5.1, *) extension Task { diff --git a/stdlib/public/Concurrency/Task+TaskExecutor.swift b/stdlib/public/Concurrency/Task+TaskExecutor.swift index 611fe9265630f..ca04d74c63afe 100644 --- a/stdlib/public/Concurrency/Task+TaskExecutor.swift +++ b/stdlib/public/Concurrency/Task+TaskExecutor.swift @@ -187,263 +187,6 @@ public func _unsafeInheritExecutor_withTaskExecutorPreference( 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 { - 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 { - 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 { diff --git a/stdlib/public/Concurrency/Task+init.swift.gyb b/stdlib/public/Concurrency/Task+init.swift.gyb new file mode 100644 index 0000000000000..2c4f544f2f172 --- /dev/null +++ b/stdlib/public/Concurrency/Task+init.swift.gyb @@ -0,0 +1,331 @@ +//===----------------------------------------------------------------------===// +// +// 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)? = 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 6.0, *)', +% ], +% [ # PARAMS +% 'name: String? = nil', +% 'executorPreference taskExecutor: (any TaskExecutor)? = nil', +% 'priority: TaskPriority? = nil', +% 'operation: sending @escaping @isolated(any) () async throws -> Success', +% ]), +% # !!!! ------------------------------------------------------------------------------------------------------------- +% # !!!! Legacy / Source compatibility APIs +% # !!!! ------------------------------------------------------------------------------------------------------------- +% # ==== Legacy API: Global 'detach' function +% ([ # METHOD_VARIANT +% 'func detach', +% 'func detach/*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', +% # FIXME: THOSE MUST NOT HAVE isolated(any) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +% '@_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', +% 'func asyncDetached/*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', +% 'func async/*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 = 'detached' in METHOD_VARIANT +% 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) +% +% 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' + +}% + +% # ==================================================================================================================== +% 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.") + } + +% # -------------------------------------------------------------------------------------------------------------------- +#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) + + // Create the asynchronous task. + let (task, _) = Builtin.createAsyncTask(flags, operation) + + self._task = task + } + +% # -------------------------------------------------------------------------------------------------------------------- +#else +% 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 task. + /// - operation: The operation to perform. + /// + /// - Returns: A reference to the task. + ${"\n ".join(adjust_availability(ALL_AVAILABILITY))} + @discardableResult + 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'}, + 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 HAS_TASK_NAME: + #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 +% end + + if task == nil { + // either no task name was set, or names are unsupported + task = Builtin.createTask( + flags: flags, + initialSerialExecutor: builtinSerialExecutor, + 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 + +// ===================================================================================================================== +// ===================================================================================================================== diff --git a/stdlib/public/Concurrency/Task.swift b/stdlib/public/Concurrency/Task.swift index bd1ed5e1650a1..a43607d56b95f 100644 --- a/stdlib/public/Concurrency/Task.swift +++ b/stdlib/public/Concurrency/Task.swift @@ -580,631 +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 { - 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 { - // 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 { - 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 { - // 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 { - 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 { - // 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 { - 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 { - // 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, *) @@ -1225,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() diff --git a/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb b/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb index 298faf73dacb8..5baad01019026 100644 --- a/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb +++ b/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb @@ -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 } diff --git a/test/Concurrency/task_naming_availability.swift b/test/Concurrency/task_naming_availability.swift new file mode 100644 index 0000000000000..c7c45d67e8216 --- /dev/null +++ b/test/Concurrency/task_naming_availability.swift @@ -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") { + () + } + } +} + From 8d9b73256505dd8bc1bf56a8b2de38b6e710b28d Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Thu, 24 Apr 2025 16:53:27 +0900 Subject: [PATCH 3/3] [Concurrency] Update Task.init and TaskGroup+addTask gyb for TaskExecutor [Concurrency] Adjust tests for renamed initializer [Embedded][Concurrency] Workaround for Gyb+concurrency module+embedded Add Task+init gyb to embedded; Remove TaskGroup+Embedded.swift workaround [Concurrency] Undo build workaround --- Runtimes/Core/Concurrency/CMakeLists.txt | 2 +- cmake/modules/SwiftSetIfArchBitness.cmake | 18 +- stdlib/public/Concurrency/CMakeLists.txt | 14 +- .../SourceCompatibilityShims.swift | 204 ++----------- stdlib/public/Concurrency/Task+init.swift.gyb | 109 ++++++- .../Concurrency/TaskGroup+Embedded.swift | 283 ------------------ .../Concurrency/TaskGroup+addTask.swift.gyb | 2 +- test/Concurrency/transfernonsendable.swift | 6 +- .../transfernonsendable_typed_errors.swift | 2 +- 9 files changed, 139 insertions(+), 501 deletions(-) delete mode 100644 stdlib/public/Concurrency/TaskGroup+Embedded.swift diff --git a/Runtimes/Core/Concurrency/CMakeLists.txt b/Runtimes/Core/Concurrency/CMakeLists.txt index dee49245fcb87..9814090041ff3 100644 --- a/Runtimes/Core/Concurrency/CMakeLists.txt +++ b/Runtimes/Core/Concurrency/CMakeLists.txt @@ -90,10 +90,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+startSynchronously.swift") diff --git a/cmake/modules/SwiftSetIfArchBitness.cmake b/cmake/modules/SwiftSetIfArchBitness.cmake index cbf16c7e754d3..8268b33f4192d 100644 --- a/cmake/modules/SwiftSetIfArchBitness.cmake +++ b/cmake/modules/SwiftSetIfArchBitness.cmake @@ -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}") diff --git a/stdlib/public/Concurrency/CMakeLists.txt b/stdlib/public/Concurrency/CMakeLists.txt index 1ccddee164eac..0a06d1bb16d3b 100644 --- a/stdlib/public/Concurrency/CMakeLists.txt +++ b/stdlib/public/Concurrency/CMakeLists.txt @@ -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 @@ -199,6 +198,12 @@ set(LLVM_OPTIONAL_SOURCES DispatchGlobalExecutor.cpp ) +set(SWIFT_CONCURRENCY_GYB_SOURCES + Task+init.swift.gyb + TaskGroup+addTask.swift.gyb + Task+startSynchronously.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} @@ -206,9 +211,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I ${SWIFT_RUNTIME_CONCURRENCY_NONEMBEDDED_SWIFT_SOURCES} GYB_SOURCES - Task+init.swift.gyb - TaskGroup+addTask.swift.gyb - Task+startSynchronously.swift.gyb + ${SWIFT_CONCURRENCY_GYB_SOURCES} SWIFT_MODULE_DEPENDS_ANDROID Android SWIFT_MODULE_DEPENDS_LINUX Glibc @@ -314,6 +317,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 diff --git a/stdlib/public/Concurrency/SourceCompatibilityShims.swift b/stdlib/public/Concurrency/SourceCompatibilityShims.swift index b63e84c795131..46364319adf99 100644 --- a/stdlib/public/Concurrency/SourceCompatibilityShims.swift +++ b/stdlib/public/Concurrency/SourceCompatibilityShims.swift @@ -14,7 +14,6 @@ //===----------------------------------------------------------------------===// import Swift -import _Concurrency @available(SwiftStdlib 5.1, *) extension Task where Success == Never, Failure == Never { @@ -88,192 +87,23 @@ 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 { -// 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 { -// 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( -// priority: TaskPriority? = nil, -// operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> T -//) -> Task { -// .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( -// priority: TaskPriority? = nil, -// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// 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( -// priority: TaskPriority? = nil, -// @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async throws -> T -//) -> Task { -// .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.") -// public typealias Group = ThrowingTaskGroup -// -// @available(*, deprecated, message: "`Task.withGroup` was replaced by `withThrowingTaskGroup` and `withTaskGroup` and will be removed shortly.") -// @_alwaysEmitIntoClient -// public static func withGroup( -// resultType: TaskResult.Type, -// returning returnType: BodyResult.Type = BodyResult.self, -// body: (inout Task.Group) async throws -> BodyResult -// ) async rethrows -> BodyResult { -// try await withThrowingTaskGroup(of: resultType) { group in -// try await body(&group) -// } -// } -//} +@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.") + public typealias Group = ThrowingTaskGroup + + @available(*, deprecated, message: "`Task.withGroup` was replaced by `withThrowingTaskGroup` and `withTaskGroup` and will be removed shortly.") + @_alwaysEmitIntoClient + public static func withGroup( + resultType: TaskResult.Type, + returning returnType: BodyResult.Type = BodyResult.self, + body: (inout Task.Group) async throws -> BodyResult + ) async rethrows -> BodyResult { + try await withThrowingTaskGroup(of: resultType) { group in + try await body(&group) + } + } +} @available(SwiftStdlib 5.1, *) extension Task { diff --git a/stdlib/public/Concurrency/Task+init.swift.gyb b/stdlib/public/Concurrency/Task+init.swift.gyb index 2c4f544f2f172..a26d43f0ad3d0 100644 --- a/stdlib/public/Concurrency/Task+init.swift.gyb +++ b/stdlib/public/Concurrency/Task+init.swift.gyb @@ -56,7 +56,8 @@ import Swift % 'name: String? = nil', % 'executorPreference taskExecutor: (any TaskExecutor)? = nil', % 'priority: TaskPriority? = nil', -% '@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success', +% # '@_inheritActorContext @_implicitSelfCapture operation: sending @escaping @isolated(any) () async throws -> Success', +% 'operation: sending @escaping () async throws -> Success', % ]), % # ==== -------------------------------------------------------------------- % ([ # METHOD_VARIANT @@ -71,10 +72,13 @@ import Swift % 'name: String? = nil', % 'executorPreference taskExecutor: (any TaskExecutor)? = nil', % 'priority: TaskPriority? = nil', -% 'operation: sending @escaping @isolated(any) () async throws -> Success', +% 'operation: sending @escaping () async throws -> Success', % ]), % # !!!! ------------------------------------------------------------------------------------------------------------- -% # !!!! Legacy / Source compatibility APIs +% # !!!! 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 @@ -88,7 +92,6 @@ import Swift % ], % [ # PARAMS % 'priority: TaskPriority? = nil', -% # FIXME: THOSE MUST NOT HAVE isolated(any) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! % '@_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping @isolated(any) () async throws -> Success', % ]), % # ==== Legacy API: runDetached @@ -138,12 +141,14 @@ import Swift % IS_TOP_LEVEL_FUNC = (not ('init' in METHOD_VARIANT)) and (not ('static' in METHOD_VARIANT)) % IS_INIT = 'init' in METHOD_VARIANT -% IS_DETACHED = 'detached' 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' @@ -195,6 +200,7 @@ extension Task where Failure == ${FAILURE_TYPE} { } % # -------------------------------------------------------------------------------------------------------------------- +% if not HAS_TASK_EXECUTOR: #elseif $Embedded @discardableResult @_alwaysEmitIntoClient @@ -213,14 +219,23 @@ extension Task where Failure == ${FAILURE_TYPE} { isDiscardingTask: false, isSynchronousStart: false) - // Create the asynchronous task. 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: @@ -262,13 +277,17 @@ extension Task where Failure == ${FAILURE_TYPE} { /// 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 task. + /// - 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}( + public ${METHOD_VARIANT}( // Task ${METHOD_VARIANT} ${",\n ".join(adjust_params_for_kind(PARAMS))} ) ${ARROW_RETURN_TYPE}{ @@ -277,37 +296,103 @@ extension Task where Failure == ${FAILURE_TYPE} { priority: priority, isChildTask: false, copyTaskLocals: ${'true' if not IS_DETACHED else 'false'}, - inheritContext: false, + inheritContext: ${'true' if not IS_DETACHED else 'false'}, enqueueJob: true, addPendingGroupTaskUnconditionally: false, isDiscardingTask: false, isSynchronousStart: false) - // Create the asynchronous task. +% 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 } - #endif -% end +% 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 } diff --git a/stdlib/public/Concurrency/TaskGroup+Embedded.swift b/stdlib/public/Concurrency/TaskGroup+Embedded.swift deleted file mode 100644 index 7aed41f538eb5..0000000000000 --- a/stdlib/public/Concurrency/TaskGroup+Embedded.swift +++ /dev/null @@ -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 diff --git a/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb b/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb index 5baad01019026..f6f4351ac25bc 100644 --- a/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb +++ b/stdlib/public/Concurrency/TaskGroup+addTask.swift.gyb @@ -315,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}( diff --git a/test/Concurrency/transfernonsendable.swift b/test/Concurrency/transfernonsendable.swift index f5ce32bd228f5..2316031ac64cd 100644 --- a/test/Concurrency/transfernonsendable.swift +++ b/test/Concurrency/transfernonsendable.swift @@ -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}} } diff --git a/test/Concurrency/transfernonsendable_typed_errors.swift b/test/Concurrency/transfernonsendable_typed_errors.swift index 72d45bac13cb5..cade1abcc2e03 100644 --- a/test/Concurrency/transfernonsendable_typed_errors.swift +++ b/test/Concurrency/transfernonsendable_typed_errors.swift @@ -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 }