//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2020-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 @_implementationOnly import SwiftConcurrencyInternalShims // ==== Task.startSynchronously ------------------------------------------------ % METHOD_VARIANTS = [ % 'THROWING', % 'NON_THROWING', % ] % OPERATION_PARAM = '@_inheritActorContext @_implicitSelfCapture _ operation: __owned @Sendable @escaping () async throws -> Success' % for METHOD_VARIANT in METHOD_VARIANTS: % IS_THROWING = METHOD_VARIANT == 'THROWING' % if IS_THROWING: % FAILURE_TYPE = 'Error' % else: % FAILURE_TYPE = 'Never' % end @available(SwiftStdlib 6.2, *) extension Task where Failure == ${FAILURE_TYPE} { /// Create and immediately start running a new task in the context of the calling thread/task. /// /// This function _starts_ the created task on the calling context. /// The task will continue executing on the caller's context until it suspends, /// and after suspension will resume on the adequate executor. For a nonisolated /// operation this means running on the global concurrent pool, and on an isolated /// operation it means the appropriate executor of that isolation context. /// /// As indicated by the lack of `async` on this method, this method does _not_ /// suspend, and instead takes over the calling task's (thread's) execution in /// a synchronous manner. /// /// Other than the execution semantics discussed above, the created task /// is semantically equivalent to its basic version which can be /// created using ``Task/init``. /// /// - Parameters: /// - name: The high-level human-readable name given for this task /// - priority: The priority of the task. /// Pass `nil` to use the ``Task/basePriority`` of the current task (if there is one). /// - operation: the operation to be run immediately upon entering the task. /// - Returns: A reference to the unstructured task which may be awaited on. @available(SwiftStdlib 6.2, *) @discardableResult public static func startSynchronously( name: String? = nil, priority: TaskPriority? = nil, @_inheritActorContext @_implicitSelfCapture _ operation: __owned sending @escaping () async throws -> Success ) -> Task { let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: true, inheritContext: true, enqueueJob: false, // don't enqueue, we'll run it manually addPendingGroupTaskUnconditionally: false, isDiscardingTask: false, isSynchronousStart: true ) var task: Builtin.NativeObject? #if $BuiltinCreateAsyncTaskName if let name { task = name.utf8CString.withUnsafeBufferPointer { nameBytes in Builtin.createTask( flags: flags, 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, operation: operation).0 } _startTaskSynchronously(task!) return Task(task!) } } %end %{ GROUP_AND_OP_INFO = [ ( 'TaskGroup', [ 'startTaskSynchronously', 'startTaskSynchronouslyUnlessCancelled' ], '', 'ChildTaskResult' ), ( 'ThrowingTaskGroup', [ 'startTaskSynchronously', 'startTaskSynchronouslyUnlessCancelled' ], 'throws ', 'ChildTaskResult' ), ( 'DiscardingTaskGroup', [ 'startTaskSynchronously', 'startTaskSynchronouslyUnlessCancelled' ], '', 'Void' ), ( 'ThrowingDiscardingTaskGroup', [ 'startTaskSynchronously', 'startTaskSynchronouslyUnlessCancelled' ], 'throws ', 'Void' ), ] }% % for (GROUP_TYPE, METHOD_NAMES, THROWS, RESULT_TYPE) in GROUP_AND_OP_INFO: % for METHOD_NAME in METHOD_NAMES: @available(SwiftStdlib 6.2, *) extension ${GROUP_TYPE} { /// Create and immediately start running a new child task in the context of the calling thread/task. /// /// This function _starts_ the created task on the calling context. /// The task will continue executing on the caller's context until it suspends, /// and after suspension will resume on the adequate executor. For a nonisolated /// operation this means running on the global concurrent pool, and on an isolated /// operation it means the appropriate executor of that isolation context. /// /// As indicated by the lack of `async` on this method, this method does _not_ /// suspend, and instead takes over the calling task's (thread's) execution in /// a synchronous manner. /// /// Other than the execution semantics discussed above, the created task /// is semantically equivalent to its basic version which can be /// created using ``${GROUP_TYPE}/addTask``. @available(SwiftStdlib 6.2, *) public func ${METHOD_NAME}( // in ${GROUP_TYPE} name: String? = nil, priority: TaskPriority? = nil, operation: sending @escaping () async ${THROWS}-> ${RESULT_TYPE} ) { let flags = taskCreateFlags( priority: priority, isChildTask: true, copyTaskLocals: false, inheritContext: false, enqueueJob: false, // don't enqueue, we'll run it manually addPendingGroupTaskUnconditionally: true, isDiscardingTask: ${'true' if 'Discarding' in GROUP_TYPE else 'false'}, isSynchronousStart: true ) // Create the task in this group. let (task, _) = Builtin.createTask( flags: flags, taskGroup: self._group, operation: operation ) _startTaskSynchronously(task) } } % end # METHOD_NAMES %end # GROUP_TYPES // ==== Legacy SPI ------------------------------------------------------------- % METHOD_VARIANTS = [ % 'THROWING', % 'NON_THROWING', % ] % OPERATION_PARAM = '@_inheritActorContext @_implicitSelfCapture _ operation: __owned @Sendable @escaping @MainActor () async throws -> Success' % for METHOD_VARIANT in METHOD_VARIANTS: % IS_THROWING = METHOD_VARIANT == 'THROWING' % if IS_THROWING: % FAILURE_TYPE = 'Error' % else: % FAILURE_TYPE = 'Never' % OPERATION_PARAM = OPERATION_PARAM.replace('throws', '') % end #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY && !SWIFT_CONCURRENCY_EMBEDDED @available(SwiftStdlib 5.9, *) extension Task where Failure == ${FAILURE_TYPE} { @_spi(MainActorUtilities) @MainActor @available(SwiftStdlib 5.9, *) @discardableResult public static func startOnMainActor( priority: TaskPriority? = nil, ${OPERATION_PARAM} ) -> Task { let flags = taskCreateFlags( priority: priority, isChildTask: false, copyTaskLocals: true, inheritContext: true, enqueueJob: false, addPendingGroupTaskUnconditionally: false, isDiscardingTask: false, isSynchronousStart: false ) let (task, _) = Builtin.createAsyncTask(flags, operation) _startTaskOnMainActor(task) return Task(task) } } #endif % end // Internal Runtime Functions -------------------------------------------------- @_silgen_name("swift_task_startOnMainActor") internal func _startTaskOnMainActor(_ task: Builtin.NativeObject) @_silgen_name("swift_task_startSynchronously") internal func _startTaskSynchronously(_ task: Builtin.NativeObject)