Skip to content

Commit e589ad0

Browse files
authored
Merge pull request #38325 from DougGregor/structured-concurrency-review-4-5.5
[SE-0304] Align Task API implementation with the fourth revision of the proposal
2 parents aecbd80 + 38a86ef commit e589ad0

File tree

9 files changed

+522
-55
lines changed

9 files changed

+522
-55
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ import Swift
2121
@frozen
2222
public struct UnownedJob {
2323
private var context: Builtin.Job
24-
25-
/// Starts running the task.
26-
public func run() { }
2724
}
2825

2926
/// A mechanism to interface

stdlib/public/Concurrency/SourceCompatibilityShims.swift

Lines changed: 48 additions & 12 deletions
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

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,20 @@ public struct TaskPriority: RawRepresentable, Sendable {
217217
}
218218

219219
public static let high: TaskPriority = .init(rawValue: 0x19)
220-
public static let userInitiated: TaskPriority = high
221-
public static let `default`: TaskPriority = .init(rawValue: 0x15)
220+
221+
@_alwaysEmitIntoClient
222+
public static var medium: TaskPriority {
223+
.init(rawValue: 0x15)
224+
}
225+
222226
public static let low: TaskPriority = .init(rawValue: 0x11)
227+
228+
public static let userInitiated: TaskPriority = high
223229
public static let utility: TaskPriority = low
224230
public static let background: TaskPriority = .init(rawValue: 0x09)
231+
232+
@available(*, deprecated, renamed: "medium")
233+
public static let `default`: TaskPriority = .init(rawValue: 0x15)
225234
}
226235

227236
@available(SwiftStdlib 5.5, *)
@@ -632,28 +641,6 @@ func _runAsyncHandler(operation: @escaping () async -> ()) {
632641
)
633642
}
634643

635-
// ==== Async Sleep ------------------------------------------------------------
636-
637-
@available(SwiftStdlib 5.5, *)
638-
extension Task where Success == Never, Failure == Never {
639-
/// Suspends the current task for _at least_ the given duration
640-
/// in nanoseconds.
641-
///
642-
/// Calling this method doesn't block the underlying thread.
643-
///
644-
/// - Parameters:
645-
/// - duration: The time to sleep, in nanoseconds.
646-
public static func sleep(_ duration: UInt64) async {
647-
let currentTask = Builtin.getCurrentAsyncTask()
648-
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
649-
650-
return await Builtin.withUnsafeContinuation { (continuation: Builtin.RawUnsafeContinuation) -> Void in
651-
let job = _taskCreateNullaryContinuationJob(priority: Int(priority.rawValue), continuation: continuation)
652-
_enqueueJobGlobalWithDelay(duration, job)
653-
}
654-
}
655-
}
656-
657644
// ==== Voluntary Suspension -----------------------------------------------------
658645

659646
@available(SwiftStdlib 5.5, *)
@@ -671,6 +658,7 @@ extension Task where Success == Never, Failure == Never {
671658
/// the executor immediately resumes execution of the same task.
672659
/// As such,
673660
/// this method isn't necessarily a way to avoid resource starvation.
661+
@available(*, deprecated, renamed: "suspend()")
674662
public static func yield() async {
675663
let currentTask = Builtin.getCurrentAsyncTask()
676664
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
@@ -680,6 +668,11 @@ extension Task where Success == Never, Failure == Never {
680668
_enqueueJobGlobal(job)
681669
}
682670
}
671+
672+
@_alwaysEmitIntoClient
673+
public static func suspend() async {
674+
await yield()
675+
}
683676
}
684677

685678
// ==== UnsafeCurrentTask ------------------------------------------------------
@@ -766,6 +759,11 @@ public struct UnsafeCurrentTask {
766759
public var priority: TaskPriority {
767760
getJobFlags(_task).priority ?? .unspecified
768761
}
762+
763+
/// Cancel the current task.
764+
public func cancel() {
765+
_taskCancel(_task)
766+
}
769767
}
770768

771769
@available(SwiftStdlib 5.5, *)

stdlib/public/Concurrency/TaskCancellation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public struct CancellationError: Error {
103103

104104
@available(SwiftStdlib 5.5, *)
105105
@_silgen_name("swift_task_addCancellationHandler")
106-
func _taskAddCancellationHandler(handler: @Sendable () -> ()) -> UnsafeRawPointer /*CancellationNotificationStatusRecord*/
106+
func _taskAddCancellationHandler(handler: () -> Void) -> UnsafeRawPointer /*CancellationNotificationStatusRecord*/
107107

108108
@available(SwiftStdlib 5.5, *)
109109
@_silgen_name("swift_task_removeCancellationHandler")

stdlib/public/Concurrency/TaskGroup.swift

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ public struct TaskGroup<ChildTaskResult> {
236236
/// - `true` if the operation was added to the group successfully,
237237
/// `false` otherwise (e.g. because the group `isCancelled`)
238238
@_alwaysEmitIntoClient
239-
public mutating func async(
239+
public mutating func addTask(
240240
priority: TaskPriority? = nil,
241241
operation: __owned @Sendable @escaping () async -> ChildTaskResult
242242
) {
@@ -270,7 +270,7 @@ public struct TaskGroup<ChildTaskResult> {
270270
/// - `true` if the operation was added to the group successfully,
271271
/// `false` otherwise (e.g. because the group `isCancelled`)
272272
@_alwaysEmitIntoClient
273-
public mutating func asyncUnlessCancelled(
273+
public mutating func addTaskUnlessCancelled(
274274
priority: TaskPriority? = nil,
275275
operation: __owned @Sendable @escaping () async -> ChildTaskResult
276276
) -> Bool {
@@ -354,7 +354,14 @@ public struct TaskGroup<ChildTaskResult> {
354354
internal mutating func awaitAllRemainingTasks() async {
355355
while let _ = await next() {}
356356
}
357-
357+
358+
/// Wait for all remaining tasks in the task group to complete before
359+
/// returning.
360+
@_alwaysEmitIntoClient
361+
public mutating func waitForAll() async {
362+
await awaitAllRemainingTasks()
363+
}
364+
358365
/// A Boolean value that indicates whether the group has any remaining tasks.
359366
///
360367
/// At the start of the body of a `withTaskGroup(of:returning:body:)` call,
@@ -444,6 +451,18 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
444451
}
445452
}
446453

454+
@usableFromInline
455+
internal mutating func _waitForAll() async throws {
456+
while let _ = try await next() { }
457+
}
458+
459+
/// Wait for all remaining tasks in the task group to complete before
460+
/// returning.
461+
@_alwaysEmitIntoClient
462+
public mutating func waitForAll() async throws {
463+
while let _ = try await next() { }
464+
}
465+
447466
/// Unconditionally create a child task in the group.
448467
///
449468
/// ### Error handling
@@ -460,7 +479,7 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
460479
/// - `true` if the operation was added to the group successfully,
461480
/// `false` otherwise (e.g. because the group `isCancelled`)
462481
@_alwaysEmitIntoClient
463-
public mutating func async(
482+
public mutating func addTask(
464483
priority: TaskPriority? = nil,
465484
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
466485
) {
@@ -494,7 +513,7 @@ public struct ThrowingTaskGroup<ChildTaskResult, Failure: Error> {
494513
/// - `true` if the operation was added to the group successfully,
495514
/// `false` otherwise (e.g. because the group `isCancelled`)
496515
@_alwaysEmitIntoClient
497-
public mutating func asyncUnlessCancelled(
516+
public mutating func addTaskUnlessCancelled(
498517
priority: TaskPriority? = nil,
499518
operation: __owned @Sendable @escaping () async throws -> ChildTaskResult
500519
) -> Bool {

0 commit comments

Comments
 (0)