Skip to content

Commit 26c521d

Browse files
committed
[Concurrency] Add new APIs to ABI check & add more tests
1 parent 29d95ce commit 26c521d

File tree

6 files changed

+265
-145
lines changed

6 files changed

+265
-145
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
140140
PartialAsyncTask.swift
141141
SourceCompatibilityShims.swift
142142
Task.swift
143+
Task+PriorityEscalation.swift
143144
Task+TaskExecutor.swift
144145
TaskCancellation.swift
145146
TaskGroup.swift
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Swift
14+
@_implementationOnly import SwiftConcurrencyInternalShims
15+
16+
// ==== Task Priority Escalation -----------------------------------------------
17+
18+
extension Task {
19+
/// Escalate the task `priority` of the passed in task to the `newPriority`.
20+
///
21+
/// - Warning: This API should rarely be used, and instead you can rely on
22+
/// structured concurrency and implicit priority escalation which happens
23+
/// when a higher priority task awaits on a result of a lower priority task.
24+
///
25+
/// I.e. using `await` on the target task usually is the correct way to
26+
/// escalate the target task to the current priority of the calling task,
27+
/// especially because in such setup if the waiting task gets escalated,
28+
/// the waited on task would be escalated automatically as well.
29+
///
30+
/// The concurrency runtime is free to interpret and handle escalation
31+
/// depending on platform characteristics.
32+
///
33+
/// Priority escalation is propagated to child tasks of the waited-on task,
34+
/// and will trigger any priority escalation handlers, if any were registered.
35+
///
36+
/// Escalation can only *increase* the priority of a task, and
37+
/// de-escalating priority is not supported.
38+
///
39+
/// This method can be called from any task or thread.
40+
///
41+
/// - Parameters:
42+
/// - task: the task which to escalate the priority of
43+
/// - newPriority: the new priority the task should continue executing on
44+
@available(SwiftStdlib 6.2, *)
45+
public static func escalatePriority(_ task: Task, to newPriority: TaskPriority) {
46+
_taskEscalate(task._task, newPriority: newPriority.rawValue)
47+
}
48+
}
49+
50+
extension UnsafeCurrentTask {
51+
/// Escalate the task `priority` of the passed in task to the `newPriority`.
52+
///
53+
/// - Warning: This API should rarely be used, and instead you can rely on
54+
/// structured concurrency and implicit priority escalation which happens
55+
/// when a higher priority task awaits on a result of a lower priority task.
56+
///
57+
/// I.e. using `await` on the target task usually is the correct way to
58+
/// escalate the target task to the current priority of the calling task,
59+
/// especially because in such setup if the waiting task gets escalated,
60+
/// the waited on task would be escalated automatically as well.
61+
///
62+
/// The concurrency runtime is free to interpret and handle escalation
63+
/// depending on platform characteristics.
64+
///
65+
/// Priority escalation is propagated to child tasks of the waited-on task,
66+
/// and will trigger any priority escalation handlers, if any were registered.
67+
///
68+
/// Escalation can only *increase* the priority of a task, and
69+
/// de-escalating priority is not supported.
70+
///
71+
/// This method can be called from any task or thread.
72+
///
73+
/// - Parameters:
74+
/// - task: the task which to escalate the priority of
75+
/// - newPriority: the new priority the task should continue executing on
76+
@available(SwiftStdlib 6.2, *)
77+
public static func escalatePriority(_ task: UnsafeCurrentTask, to newPriority: TaskPriority) {
78+
_taskEscalate(task._task, newPriority: newPriority.rawValue)
79+
}
80+
}
81+
82+
// ==== Task Priority Escalation Handlers --------------------------------------
83+
84+
/// Runs the passed `operation` while registering a task priority escalation handler.
85+
/// The handler will be triggered concurrently to the current task if the current
86+
/// is subject to priority escalation.
87+
///
88+
/// The handler may perform additional actions upon priority escalation,
89+
/// but cannot influence how the escalation influences the task, i.e. the task's
90+
/// priority will be escalated regardless of actions performed in the handler.
91+
///
92+
/// The handler will only trigger if a priority escalation occurs while the
93+
/// operation is in progress.
94+
///
95+
/// If multiple task escalation handlers are nester they will all be triggered.
96+
///
97+
/// Task escalation propagates through structured concurrency child-tasks.
98+
///
99+
/// - Parameters:
100+
/// - operation: the operation during which to listen for priority escalation
101+
/// - handler: handler to invoke, concurrently to `operation`,
102+
/// when priority escalation happens
103+
/// - Returns: the value returned by `operation`
104+
/// - Throws: when the `operation` throws an error
105+
@available(SwiftStdlib 6.2, *)
106+
public func withTaskPriorityEscalationHandler<T, E>(
107+
operation: () async throws(E) -> T,
108+
onPriorityEscalated handler: @Sendable (TaskPriority) -> Void,
109+
isolation: isolated (any Actor)? = #isolation
110+
) async throws(E) -> T {
111+
// NOTE: We have to create the closure beforehand as otherwise it seems
112+
// the task-local allocator may be used and we end up violating stack-discipline
113+
// when releasing the handler closure vs. the record.
114+
let handler0: (UInt8) -> Void = {
115+
handler(TaskPriority(rawValue: $0))
116+
}
117+
let record = _taskAddPriorityEscalationHandler(handler: handler0)
118+
defer { _taskRemovePriorityEscalationHandler(record: record) }
119+
120+
return try await operation()
121+
}

stdlib/public/Concurrency/Task.swift

Lines changed: 1 addition & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -900,106 +900,6 @@ extension Task where Success == Never, Failure == Never {
900900
}
901901
}
902902

903-
// ==== Manual Priority Escalation ---------------------------------------------
904-
905-
extension Task {
906-
/// Escalate the task `priority` of the passed in task to the `newPriority`.
907-
///
908-
/// - Warning: This API should rarely be used, and instead you can rely on
909-
/// structured concurrency and implicit priority escalation which happens
910-
/// when a higher priority task awaits on a result of a lower priority task.
911-
///
912-
/// I.e. using `await` on the target task usually is the correct way to
913-
/// escalate the target task to the current priority of the calling task,
914-
/// especially because in such setup if the waiting task gets escalated,
915-
/// the waited on task would be escalated automatically as well.
916-
///
917-
/// The concurrency runtime is free to interpret and handle escalation
918-
/// depending on platform characteristics.
919-
///
920-
/// Priority escalation is propagated to child tasks of the waited-on task,
921-
/// and will trigger any priority escalation handlers, if any were registered.
922-
///
923-
/// Escalation can only *increase* the priority of a task, and
924-
/// de-escalating priority is not supported.
925-
///
926-
/// This method can be called from any task or thread.
927-
///
928-
/// - Parameters:
929-
/// - task: the task which to escalate the priority of
930-
/// - newPriority: the new priority the task should continue executing on
931-
@available(SwiftStdlib 9999, *)
932-
public static func escalatePriority(_ task: Task, to newPriority: TaskPriority) {
933-
_taskEscalate(task._task, newPriority: newPriority.rawValue)
934-
}
935-
936-
/// Escalate the task `priority` of the passed in task to the `newPriority`.
937-
///
938-
/// - Warning: This API should rarely be used, and instead you can rely on
939-
/// structured concurrency and implicit priority escalation which happens
940-
/// when a higher priority task awaits on a result of a lower priority task.
941-
///
942-
/// I.e. using `await` on the target task usually is the correct way to
943-
/// escalate the target task to the current priority of the calling task,
944-
/// especially because in such setup if the waiting task gets escalated,
945-
/// the waited on task would be escalated automatically as well.
946-
///
947-
/// The concurrency runtime is free to interpret and handle escalation
948-
/// depending on platform characteristics.
949-
///
950-
/// Priority escalation is propagated to child tasks of the waited-on task,
951-
/// and will trigger any priority escalation handlers, if any were registered.
952-
///
953-
/// Escalation can only *increase* the priority of a task, and
954-
/// de-escalating priority is not supported.
955-
///
956-
/// This method can be called from any task or thread.
957-
///
958-
/// - Parameters:
959-
/// - task: the task which to escalate the priority of
960-
/// - newPriority: the new priority the task should continue executing on
961-
@available(SwiftStdlib 9999, *)
962-
public static func escalatePriority(_ task: UnsafeCurrentTask, to newPriority: TaskPriority) {
963-
_taskEscalate(task._task, newPriority: newPriority.rawValue)
964-
}
965-
}
966-
967-
/// Runs the passed `operation` while registering a task priority escalation handler.
968-
/// The handler will be triggered concurrently to the current task if the current
969-
/// is subject to priority escalation.
970-
///
971-
/// The handler may perform additional actions upon priority escalation,
972-
/// but cannot influence how the escalation influences the task, i.e. the task's
973-
/// priority will be escalated regardless of actions performed in the handler.
974-
///
975-
/// If multiple task escalation handlers are nester they will all be triggered.
976-
///
977-
/// Task escalation propagates through structured concurrency child-tasks.
978-
///
979-
/// - Parameters:
980-
/// - operation: the operation during which to listen for priority escalation
981-
/// - handler: handler to invoke, concurrently to `operation`,
982-
/// when priority escalation happens
983-
/// - Returns: the value returned by `operation`
984-
/// - Throws: when the `operation` throws an error
985-
@available(SwiftStdlib 9999, *)
986-
public func withTaskPriorityEscalationHandler<T, E>(
987-
operation: () async throws(E) -> T,
988-
onEscalate handler: @Sendable (TaskPriority) -> Void,
989-
isolation: isolated (any Actor)? = #isolation
990-
) async throws(E) -> T {
991-
// NOTE: We have to create the closure beforehand as otherwise it seems
992-
// the task-local allocator may be used and we end up violating stack-discipline
993-
// when releasing the handler closure vs. the record.
994-
let handler0: (UInt8) -> Void = {
995-
handler(TaskPriority(rawValue: $0))
996-
}
997-
let record = _taskAddPriorityEscalationHandler(handler: handler0)
998-
defer { _taskRemovePriorityEscalationHandler(record: record) }
999-
1000-
return try await operation()
1001-
}
1002-
1003903
// ==== UnsafeCurrentTask ------------------------------------------------------
1004904

1005905
/// Calls a closure with an unsafe reference to the current task.
@@ -1266,7 +1166,7 @@ func _taskIsCancelled(_ task: Builtin.NativeObject) -> Bool
12661166
@_silgen_name("swift_task_currentPriority")
12671167
internal func _taskCurrentPriority(_ task: Builtin.NativeObject) -> UInt8
12681168

1269-
@available(SwiftStdlib 9999, *) // TODO: determine how far back this can back-deploy because it already was in runtime
1169+
@available(SwiftStdlib 6.2, *)
12701170
@_silgen_name("swift_task_escalate")
12711171
internal func _taskEscalate(_ task: Builtin.NativeObject, newPriority: UInt8)
12721172

0 commit comments

Comments
 (0)