Skip to content

Commit 907b0e6

Browse files
committed
add Task.detached(_on:) which was missing
1 parent 8af2bd9 commit 907b0e6

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

stdlib/public/Concurrency/Task+TaskExecutor.swift

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,139 @@ extension Task where Failure == Error {
155155
}
156156
}
157157

158+
// ==== Detached tasks ---------------------------------------------------------
159+
160+
@available(SwiftStdlib 9999, *)
161+
extension Task where Failure == Never {
162+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
163+
@discardableResult
164+
@_alwaysEmitIntoClient
165+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
166+
public static func _detached(
167+
on executor: any _TaskExecutor,
168+
priority: TaskPriority? = nil,
169+
operation: __owned @Sendable @escaping () async -> Success
170+
) -> Task<Success, Failure> {
171+
fatalError("Unavailable in task-to-thread concurrency model")
172+
}
173+
#else
174+
/// Runs the given nonthrowing operation asynchronously
175+
/// as part of a new top-level task.
176+
///
177+
/// Don't use a detached task if it's possible
178+
/// to model the operation using structured concurrency features like child tasks.
179+
/// Child tasks inherit the parent task's priority and task-local storage,
180+
/// and canceling a parent task automatically cancels all of its child tasks.
181+
/// You need to handle these considerations manually with a detached task.
182+
///
183+
/// You need to keep a reference to the detached task
184+
/// if you want to cancel it by calling the `Task.cancel()` method.
185+
/// Discarding your reference to a detached task
186+
/// doesn't implicitly cancel that task,
187+
/// it only makes it impossible for you to explicitly cancel the task.
188+
///
189+
/// - Parameters:
190+
/// - executor: The task executor preference to use for this task.
191+
/// - priority: The priority of the task.
192+
/// - operation: The operation to perform.
193+
///
194+
/// - Returns: A reference to the task.
195+
@discardableResult
196+
@_alwaysEmitIntoClient
197+
public static func _detached(
198+
on executor: any _TaskExecutor,
199+
priority: TaskPriority? = nil,
200+
operation: __owned @Sendable @escaping () async -> Success
201+
) -> Task<Success, Failure> {
202+
#if $BuiltinCreateAsyncTaskWithExecutor
203+
// Set up the job flags for a new task.
204+
let flags = taskCreateFlags(
205+
priority: priority, isChildTask: false, copyTaskLocals: false,
206+
inheritContext: false, enqueueJob: true,
207+
addPendingGroupTaskUnconditionally: false,
208+
isDiscardingTask: false)
209+
210+
// Create the asynchronous task.
211+
let taskExecutorRef = executor.asUnownedTaskExecutor()
212+
let (task, _) = Builtin.createAsyncTaskWithExecutor(
213+
flags, taskExecutorRef.executor, operation)
214+
215+
return Task(task)
216+
#else
217+
fatalError("Unsupported Swift compiler")
218+
#endif
219+
}
220+
#endif
221+
}
222+
223+
@available(SwiftStdlib 9999, *)
224+
extension Task where Failure == Error {
225+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
226+
@discardableResult
227+
@_alwaysEmitIntoClient
228+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model")
229+
public static func _detached(
230+
on executor: any _TaskExecutor,
231+
priority: TaskPriority? = nil,
232+
operation: __owned @Sendable @escaping () async throws -> Success
233+
) -> Task<Success, Failure> {
234+
fatalError("Unavailable in task-to-thread concurrency model")
235+
}
236+
#else
237+
/// Runs the given throwing operation asynchronously
238+
/// as part of a new top-level task.
239+
///
240+
/// If the operation throws an error, this method propagates that error.
241+
///
242+
/// Don't use a detached task if it's possible
243+
/// to model the operation using structured concurrency features like child tasks.
244+
/// Child tasks inherit the parent task's priority and task-local storage,
245+
/// and canceling a parent task automatically cancels all of its child tasks.
246+
/// You need to handle these considerations manually with a detached task.
247+
///
248+
/// You need to keep a reference to the detached task
249+
/// if you want to cancel it by calling the `Task.cancel()` method.
250+
/// Discarding your reference to a detached task
251+
/// doesn't implicitly cancel that task,
252+
/// it only makes it impossible for you to explicitly cancel the task.
253+
///
254+
/// - Parameters:
255+
/// - executor: The task executor preference to use for this task.
256+
/// - priority: The priority of the task.
257+
/// - operation: The operation to perform.
258+
///
259+
/// - Returns: A reference to the task.
260+
@discardableResult
261+
@_alwaysEmitIntoClient
262+
public static func _detached(
263+
on executor: any _TaskExecutor,
264+
priority: TaskPriority? = nil,
265+
operation: __owned @Sendable @escaping () async throws -> Success
266+
) -> Task<Success, Failure> {
267+
#if $BuiltinCreateAsyncTaskWithExecutor
268+
// Set up the job flags for a new task.
269+
let flags = taskCreateFlags(
270+
priority: priority, isChildTask: false, copyTaskLocals: false,
271+
inheritContext: false, enqueueJob: true,
272+
addPendingGroupTaskUnconditionally: false,
273+
isDiscardingTask: false)
274+
275+
// Create the asynchronous task.
276+
// Create the asynchronous task.
277+
let taskExecutorRef = executor.asUnownedTaskExecutor()
278+
let (task, _) = Builtin.createAsyncTaskWithExecutor(
279+
flags, taskExecutorRef.executor, operation)
280+
281+
return Task(task)
282+
#else
283+
fatalError("Unsupported Swift compiler")
284+
#endif
285+
}
286+
#endif
287+
}
288+
289+
// ==== Unsafe Current Task ----------------------------------------------------
290+
158291
@available(SwiftStdlib 9999, *)
159292
extension UnsafeCurrentTask {
160293

stdlib/public/Concurrency/Task.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ extension Task where Failure == Error {
720720
}
721721

722722
// ==== Detached Tasks ---------------------------------------------------------
723+
723724
@available(SwiftStdlib 5.1, *)
724725
extension Task where Failure == Never {
725726
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

0 commit comments

Comments
 (0)