Skip to content

Commit 57e22bb

Browse files
authored
Merge pull request #38306 from DougGregor/structured-concurrency-review-4
[SE-0304] Align Task API implementation with the fourth revision of the proposal
2 parents 398d07f + 121e34f commit 57e22bb

9 files changed

+523
-51
lines changed

stdlib/public/Concurrency/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
7070
TaskGroup.swift
7171
TaskLocal.cpp
7272
TaskLocal.swift
73+
TaskSleep.swift
7374
ThreadSanitizer.cpp
7475
Mutex.cpp
7576
AsyncStreamBuffer.swift

stdlib/public/Concurrency/PartialAsyncTask.swift

-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ import Swift
1818
@frozen
1919
public struct UnownedJob {
2020
private var context: Builtin.Job
21-
22-
public func run() { }
2321
}
2422

2523
@available(SwiftStdlib 5.5, *)

stdlib/public/Concurrency/SourceCompatibilityShims.swift

+48-12
Original file line numberDiff line numberDiff line change
@@ -190,65 +190,101 @@ extension Task where Failure == Never {
190190

191191
@available(SwiftStdlib 5.5, *)
192192
extension TaskGroup {
193-
@available(*, deprecated, renamed: "async(priority:operation:)")
193+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
194194
@_alwaysEmitIntoClient
195195
public mutating func add(
196196
priority: TaskPriority? = nil,
197197
operation: __owned @Sendable @escaping () async -> ChildTaskResult
198198
) async -> Bool {
199-
return self.asyncUnlessCancelled(priority: priority) {
199+
return self.addTaskUnlessCancelled(priority: priority) {
200200
await operation()
201201
}
202202
}
203203

204-
@available(*, deprecated, renamed: "async(priority:operation:)")
204+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
205205
@_alwaysEmitIntoClient
206206
public mutating func spawn(
207207
priority: TaskPriority? = nil,
208208
operation: __owned @Sendable @escaping () async -> ChildTaskResult
209209
) {
210-
async(priority: priority, operation: operation)
210+
addTask(priority: priority, operation: operation)
211211
}
212212

213-
@available(*, deprecated, renamed: "asyncUnlessCancelled(priority:operation:)")
213+
@available(*, deprecated, renamed: "addTaskUnlessCancelled(priority:operation:)")
214214
@_alwaysEmitIntoClient
215215
public mutating func spawnUnlessCancelled(
216216
priority: TaskPriority? = nil,
217217
operation: __owned @Sendable @escaping () async -> ChildTaskResult
218218
) -> Bool {
219-
asyncUnlessCancelled(priority: priority, operation: operation)
219+
addTaskUnlessCancelled(priority: priority, operation: operation)
220+
}
221+
222+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
223+
@_alwaysEmitIntoClient
224+
public mutating func async(
225+
priority: TaskPriority? = nil,
226+
operation: __owned @Sendable @escaping () async -> ChildTaskResult
227+
) {
228+
addTask(priority: priority, operation: operation)
229+
}
230+
231+
@available(*, deprecated, renamed: "addTaskUnlessCancelled(priority:operation:)")
232+
@_alwaysEmitIntoClient
233+
public mutating func asyncUnlessCancelled(
234+
priority: TaskPriority? = nil,
235+
operation: __owned @Sendable @escaping () async -> ChildTaskResult
236+
) -> Bool {
237+
addTaskUnlessCancelled(priority: priority, operation: operation)
220238
}
221239
}
222240

223241
@available(SwiftStdlib 5.5, *)
224242
extension ThrowingTaskGroup {
225-
@available(*, deprecated, renamed: "async(priority:operation:)")
243+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
226244
@_alwaysEmitIntoClient
227245
public mutating func add(
228246
priority: TaskPriority? = nil,
229247
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
230248
) async -> Bool {
231-
return self.asyncUnlessCancelled(priority: priority) {
249+
return self.addTaskUnlessCancelled(priority: priority) {
232250
try await operation()
233251
}
234252
}
235253

236-
@available(*, deprecated, renamed: "async(priority:operation:)")
254+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
237255
@_alwaysEmitIntoClient
238256
public mutating func spawn(
239257
priority: TaskPriority? = nil,
240258
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
241259
) {
242-
async(priority: priority, operation: operation)
260+
addTask(priority: priority, operation: operation)
243261
}
244262

245-
@available(*, deprecated, renamed: "asyncUnlessCancelled(priority:operation:)")
263+
@available(*, deprecated, renamed: "addTaskUnlessCancelled(priority:operation:)")
246264
@_alwaysEmitIntoClient
247265
public mutating func spawnUnlessCancelled(
248266
priority: TaskPriority? = nil,
249267
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
250268
) -> Bool {
251-
asyncUnlessCancelled(priority: priority, operation: operation)
269+
addTaskUnlessCancelled(priority: priority, operation: operation)
270+
}
271+
272+
@available(*, deprecated, renamed: "addTask(priority:operation:)")
273+
@_alwaysEmitIntoClient
274+
public mutating func async(
275+
priority: TaskPriority? = nil,
276+
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
277+
) {
278+
addTask(priority: priority, operation: operation)
279+
}
280+
281+
@available(*, deprecated, renamed: "addTaskUnlessCancelled(priority:operation:)")
282+
@_alwaysEmitIntoClient
283+
public mutating func asyncUnlessCancelled(
284+
priority: TaskPriority? = nil,
285+
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
286+
) -> Bool {
287+
addTaskUnlessCancelled(priority: priority, operation: operation)
252288
}
253289
}
254290

stdlib/public/Concurrency/Task.swift

+23-21
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,20 @@ public struct TaskPriority: RawRepresentable, Sendable {
202202
}
203203

204204
public static let high: TaskPriority = .init(rawValue: 0x19)
205-
public static let userInitiated: TaskPriority = high
206-
public static let `default`: TaskPriority = .init(rawValue: 0x15)
205+
206+
@_alwaysEmitIntoClient
207+
public static var medium: TaskPriority {
208+
.init(rawValue: 0x15)
209+
}
210+
207211
public static let low: TaskPriority = .init(rawValue: 0x11)
212+
213+
public static let userInitiated: TaskPriority = high
208214
public static let utility: TaskPriority = low
209215
public static let background: TaskPriority = .init(rawValue: 0x09)
216+
217+
@available(*, deprecated, renamed: "medium")
218+
public static let `default`: TaskPriority = .init(rawValue: 0x15)
210219
}
211220

212221
@available(SwiftStdlib 5.5, *)
@@ -606,25 +615,6 @@ extension Task where Failure == Error {
606615
}
607616
}
608617

609-
// ==== Async Sleep ------------------------------------------------------------
610-
611-
@available(SwiftStdlib 5.5, *)
612-
extension Task where Success == Never, Failure == Never {
613-
/// Suspends the current task for _at least_ the given duration
614-
/// in nanoseconds.
615-
///
616-
/// This function does _not_ block the underlying thread.
617-
public static func sleep(_ duration: UInt64) async {
618-
let currentTask = Builtin.getCurrentAsyncTask()
619-
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
620-
621-
return await Builtin.withUnsafeContinuation { (continuation: Builtin.RawUnsafeContinuation) -> Void in
622-
let job = _taskCreateNullaryContinuationJob(priority: Int(priority.rawValue), continuation: continuation)
623-
_enqueueJobGlobalWithDelay(duration, job)
624-
}
625-
}
626-
}
627-
628618
// ==== Voluntary Suspension -----------------------------------------------------
629619

630620
@available(SwiftStdlib 5.5, *)
@@ -636,6 +626,8 @@ extension Task where Success == Never, Failure == Never {
636626
/// This is not a perfect cure for starvation;
637627
/// if the task is the highest-priority task in the system, it might go
638628
/// immediately back to executing.
629+
///
630+
@available(*, deprecated, renamed: "suspend()")
639631
public static func yield() async {
640632
let currentTask = Builtin.getCurrentAsyncTask()
641633
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
@@ -645,6 +637,11 @@ extension Task where Success == Never, Failure == Never {
645637
_enqueueJobGlobal(job)
646638
}
647639
}
640+
641+
@_alwaysEmitIntoClient
642+
public static func suspend() async {
643+
await yield()
644+
}
648645
}
649646

650647
// ==== UnsafeCurrentTask ------------------------------------------------------
@@ -715,6 +712,11 @@ public struct UnsafeCurrentTask {
715712
public var priority: TaskPriority {
716713
getJobFlags(_task).priority ?? .unspecified
717714
}
715+
716+
/// Cancel the current task.
717+
public func cancel() {
718+
_taskCancel(_task)
719+
}
718720
}
719721

720722
@available(SwiftStdlib 5.5, *)

stdlib/public/Concurrency/TaskCancellation.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public struct CancellationError: Error {
112112

113113
@available(SwiftStdlib 5.5, *)
114114
@_silgen_name("swift_task_addCancellationHandler")
115-
func _taskAddCancellationHandler(handler: @Sendable () -> Void) -> UnsafeRawPointer /*CancellationNotificationStatusRecord*/
115+
func _taskAddCancellationHandler(handler: () -> Void) -> UnsafeRawPointer /*CancellationNotificationStatusRecord*/
116116

117117
@available(SwiftStdlib 5.5, *)
118118
@_silgen_name("swift_task_removeCancellationHandler")

stdlib/public/Concurrency/TaskGroup.swift

+24-5
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ public struct TaskGroup<ChildTaskResult> {
208208
/// - `true` if the operation was added to the group successfully,
209209
/// `false` otherwise (e.g. because the group `isCancelled`)
210210
@_alwaysEmitIntoClient
211-
public mutating func async(
211+
public mutating func addTask(
212212
priority: TaskPriority? = nil,
213213
operation: __owned @Sendable @escaping () async -> ChildTaskResult
214214
) {
@@ -242,7 +242,7 @@ public struct TaskGroup<ChildTaskResult> {
242242
/// - `true` if the operation was added to the group successfully,
243243
/// `false` otherwise (e.g. because the group `isCancelled`)
244244
@_alwaysEmitIntoClient
245-
public mutating func asyncUnlessCancelled(
245+
public mutating func addTaskUnlessCancelled(
246246
priority: TaskPriority? = nil,
247247
operation: __owned @Sendable @escaping () async -> ChildTaskResult
248248
) -> Bool {
@@ -333,7 +333,14 @@ public struct TaskGroup<ChildTaskResult> {
333333
internal mutating func awaitAllRemainingTasks() async {
334334
while let _ = await next() {}
335335
}
336-
336+
337+
/// Wait for all remaining tasks in the task group to complete before
338+
/// returning.
339+
@_alwaysEmitIntoClient
340+
public mutating func waitForAll() async {
341+
await awaitAllRemainingTasks()
342+
}
343+
337344
/// Query whether the group has any remaining tasks.
338345
///
339346
/// Task groups are always empty upon entry to the `withTaskGroup` body, and
@@ -424,6 +431,18 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
424431
}
425432
}
426433

434+
@usableFromInline
435+
internal mutating func _waitForAll() async throws {
436+
while let _ = try await next() { }
437+
}
438+
439+
/// Wait for all remaining tasks in the task group to complete before
440+
/// returning.
441+
@_alwaysEmitIntoClient
442+
public mutating func waitForAll() async throws {
443+
while let _ = try await next() { }
444+
}
445+
427446
/// Spawn, unconditionally, a child task in the group.
428447
///
429448
/// ### Error handling
@@ -440,7 +459,7 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
440459
/// - `true` if the operation was added to the group successfully,
441460
/// `false` otherwise (e.g. because the group `isCancelled`)
442461
@_alwaysEmitIntoClient
443-
public mutating func async(
462+
public mutating func addTask(
444463
priority: TaskPriority? = nil,
445464
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
446465
) {
@@ -474,7 +493,7 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
474493
/// - `true` if the operation was added to the group successfully,
475494
/// `false` otherwise (e.g. because the group `isCancelled`)
476495
@_alwaysEmitIntoClient
477-
public mutating func asyncUnlessCancelled(
496+
public mutating func addTaskUnlessCancelled(
478497
priority: TaskPriority? = nil,
479498
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
480499
) -> Bool {

0 commit comments

Comments
 (0)