Skip to content

Commit be8838a

Browse files
committed
[Concurrency] UnownedJob.priority and description for TaskPriority
1 parent 97b68be commit be8838a

File tree

5 files changed

+114
-4
lines changed

5 files changed

+114
-4
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,11 @@ SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
561561
JobPriority
562562
swift_task_basePriority(AsyncTask *task);
563563

564+
/// Returns the priority of the job.
565+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
566+
JobPriority
567+
swift_concurrency_jobPriority(Job *job);
568+
564569
/// Create and add an cancellation record to the task.
565570
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
566571
CancellationNotificationStatusRecord*

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,33 @@ internal func _swiftJobRun(_ job: UnownedJob,
2828
public struct UnownedJob: Sendable {
2929
private var context: Builtin.Job
3030

31+
@available(SwiftStdlib 5.9, *)
32+
public var priority: Priority {
33+
let raw = _swift_concurrency_jobPriority(self)
34+
return Priority(rawValue: raw)
35+
}
36+
3137
@_alwaysEmitIntoClient
3238
@inlinable
3339
public func _runSynchronously(on executor: UnownedSerialExecutor) {
3440
_swiftJobRun(self, executor)
3541
}
3642
}
3743

44+
@available(SwiftStdlib 5.1, *)
45+
extension UnownedJob {
46+
public struct Priority {
47+
public typealias RawValue = UInt8
48+
public var rawValue: RawValue
49+
50+
/// Convert this ``UnownedJob/Priority`` to a ``TaskPriority``.
51+
public var asTaskPriority: TaskPriority? {
52+
// TODO: what if it was JobPriority::Undefined?
53+
TaskPriority(rawValue: self.rawValue)
54+
}
55+
}
56+
}
57+
3858
/// A mechanism to interface
3959
/// between synchronous and asynchronous code,
4060
/// without correctness checking.
@@ -291,3 +311,7 @@ public func withUnsafeThrowingContinuation<T>(
291311
public func _abiEnableAwaitContinuation() {
292312
fatalError("never use this function")
293313
}
314+
315+
@available(SwiftStdlib 5.8, *)
316+
@_silgen_name("swift_concurrency_jobPriority")
317+
public func _swift_concurrency_jobPriority(_ job: UnownedJob) -> UInt8

stdlib/public/Concurrency/Task.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,20 +592,22 @@ const void *AsyncTask::getResumeFunctionForLogging() {
592592
return __ptrauth_swift_runtime_function_entry_strip(result);
593593
}
594594

595-
JobPriority swift::swift_task_currentPriority(AsyncTask *task)
596-
{
595+
JobPriority swift::swift_task_currentPriority(AsyncTask *task) {
597596
// This is racey but this is to be used in an API is inherently racey anyways.
598597
auto oldStatus = task->_private()._status().load(std::memory_order_relaxed);
599598
return oldStatus.getStoredPriority();
600599
}
601600

602-
JobPriority swift::swift_task_basePriority(AsyncTask *task)
603-
{
601+
JobPriority swift::swift_task_basePriority(AsyncTask *task) {
604602
JobPriority pri = task->_private().BasePriority;
605603
SWIFT_TASK_DEBUG_LOG("Task %p has base priority = %zu", task, pri);
606604
return pri;
607605
}
608606

607+
JobPriority swift::swift_concurrency_jobPriority(Job *job) {
608+
return job->getPriority();
609+
}
610+
609611
static inline bool isUnspecified(JobPriority priority) {
610612
return priority == JobPriority::Unspecified;
611613
}

stdlib/public/Concurrency/Task.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,25 @@ extension TaskPriority: Comparable {
273273
}
274274
}
275275

276+
277+
@available(SwiftStdlib 5.9, *)
278+
extension TaskPriority: CustomStringConvertible {
279+
public var description: String {
280+
switch self.rawValue {
281+
case Self.low.rawValue:
282+
return "\(Self.self).low"
283+
case Self.medium.rawValue:
284+
return "\(Self.self).medium"
285+
case Self.high.rawValue:
286+
return "\(Self.self).high"
287+
case Self.background.rawValue:
288+
return "\(Self.self).background"
289+
default:
290+
return "\(Self.self)(rawValue: \(self.rawValue))"
291+
}
292+
}
293+
}
294+
276295
@available(SwiftStdlib 5.1, *)
277296
extension TaskPriority: Codable { }
278297

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library) | %FileCheck %s
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: executable_test
5+
// UNSUPPORTED: freestanding
6+
7+
// UNSUPPORTED: back_deployment_runtime
8+
// REQUIRES: concurrency_runtime
9+
10+
final class InlineExecutor: SerialExecutor {
11+
public func enqueue(_ job: UnownedJob) {
12+
print("\(self): enqueue (priority: \(job.priority.asTaskPriority!))")
13+
job._runSynchronously(on: self.asUnownedSerialExecutor())
14+
}
15+
16+
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
17+
return UnownedSerialExecutor(ordinary: self)
18+
}
19+
}
20+
21+
let inlineExecutor = InlineExecutor()
22+
23+
actor Custom {
24+
var count = 0
25+
26+
@available(SwiftStdlib 5.1, *)
27+
nonisolated var unownedExecutor: UnownedSerialExecutor {
28+
print("custom unownedExecutor")
29+
return inlineExecutor.asUnownedSerialExecutor()
30+
}
31+
32+
func report() async {
33+
print("custom.count == \(count)")
34+
count += 1
35+
}
36+
}
37+
38+
@available(SwiftStdlib 5.1, *)
39+
@main struct Main {
40+
static func main() async {
41+
print("begin")
42+
let actor = Custom()
43+
await Task(priority: .high) {
44+
await actor.report()
45+
}.value
46+
await Task() {
47+
await actor.report()
48+
}.value
49+
print("end")
50+
}
51+
}
52+
53+
// CHECK: begin
54+
// CHECK-NEXT: custom unownedExecutor
55+
// CHECK-NEXT: main.InlineExecutor: enqueue (priority: TaskPriority.high)
56+
// CHECK-NEXT: custom.count == 0
57+
// CHECK-NEXT: custom unownedExecutor
58+
// CHECK-NEXT: main.InlineExecutor: enqueue (priority: TaskPriority.medium)
59+
// CHECK-NEXT: custom.count == 1
60+
// CHECK-NEXT: end

0 commit comments

Comments
 (0)