Skip to content

Commit 00e7ef2

Browse files
committed
[Concurrency] Remove EventableExecutor, alter asSchedulable.
EventableExecutor is being removed, for now, but hopefully will return in some form in the future. The `asSchedulable` implementation needs to change for reasons of ABI stability. rdar://141348916
1 parent 444bbd5 commit 00e7ef2

File tree

10 files changed

+73
-240
lines changed

10 files changed

+73
-240
lines changed

stdlib/public/Concurrency/DispatchExecutor.swift

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import Swift
2525

2626
@available(SwiftStdlib 6.2, *)
2727
public class DispatchMainExecutor: RunLoopExecutor, @unchecked Sendable {
28-
public typealias AsSchedulable = DispatchMainExecutor
29-
3028
var threaded = false
3129

3230
public init() {}
@@ -61,6 +59,10 @@ extension DispatchMainExecutor: SerialExecutor {
6159

6260
@available(SwiftStdlib 6.2, *)
6361
extension DispatchMainExecutor: SchedulableExecutor {
62+
public var asSchedulable: SchedulableExecutor? {
63+
return self
64+
}
65+
6466
public func enqueue<C: Clock>(_ job: consuming ExecutorJob,
6567
at instant: C.Instant,
6668
tolerance: C.Duration? = nil,
@@ -83,36 +85,6 @@ extension DispatchMainExecutor: SchedulableExecutor {
8385
}
8486
}
8587

86-
@available(SwiftStdlib 6.2, *)
87-
extension DispatchMainExecutor: EventableExecutor {
88-
89-
/// Register a new event with a given handler.
90-
public func registerEvent(
91-
handler: @escaping @Sendable () -> ()
92-
) -> ExecutorEvent {
93-
let source = unsafe _createDispatchEvent(handler: handler)
94-
95-
// Stash the pointer in the id of the ExecutorEvent struct
96-
let eventId = unsafe unsafeBitCast(source, to: Int.self)
97-
return ExecutorEvent(id: eventId)
98-
}
99-
100-
/// Deregister the given event.
101-
public func deregister(event: ExecutorEvent) {
102-
// Extract the source and cancel it
103-
let source = unsafe unsafeBitCast(event.id, to: OpaquePointer.self)
104-
unsafe _destroyDispatchEvent(source)
105-
}
106-
107-
/// Notify the executor of an event.
108-
public func notify(event: ExecutorEvent) {
109-
// Extract the source, but don't release it
110-
let source = unsafe unsafeBitCast(event.id, to: OpaquePointer.self)
111-
unsafe _signalDispatchEvent(source)
112-
}
113-
114-
}
115-
11688
@available(SwiftStdlib 6.2, *)
11789
extension DispatchMainExecutor: MainExecutor {}
11890

@@ -121,9 +93,6 @@ extension DispatchMainExecutor: MainExecutor {}
12193
@available(SwiftStdlib 6.2, *)
12294
public class DispatchGlobalTaskExecutor: TaskExecutor, SchedulableExecutor,
12395
@unchecked Sendable {
124-
125-
public typealias AsSchedulable = DispatchGlobalTaskExecutor
126-
12796
public init() {}
12897

12998
public func enqueue(_ job: consuming ExecutorJob) {

stdlib/public/Concurrency/Executor.swift

Lines changed: 12 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ import Swift
1616
@available(SwiftStdlib 5.1, *)
1717
public protocol Executor: AnyObject, Sendable {
1818

19-
/// This Executor type as a schedulable executor.
20-
///
21-
/// If the conforming type also conforms to `SchedulableExecutor`, then this is
22-
/// bound to `Self`. Otherwise, it is an uninhabited type (such as Never).
23-
@available(SwiftStdlib 6.2, *)
24-
associatedtype AsSchedulable: SchedulableExecutor = SchedulableExecutorNever
25-
2619
// Since lack move-only type support in the SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY configuration
2720
// Do not deprecate the UnownedJob enqueue in that configuration just yet - as we cannot introduce the replacements.
2821
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@@ -55,23 +48,8 @@ public protocol Executor: AnyObject, Sendable {
5548
#endif
5649
}
5750

58-
/// Uninhabited class type to indicate we don't support scheduling.
59-
@available(SwiftStdlib 6.2, *)
60-
public class SchedulableExecutorNever {
61-
private init(_ n: Never) {}
62-
}
63-
6451
@available(SwiftStdlib 6.2, *)
65-
extension SchedulableExecutorNever: SchedulableExecutor, @unchecked Sendable {
66-
67-
public func enqueue(_ job: consuming ExecutorJob) {
68-
fatalError("This should never be reached")
69-
}
70-
71-
}
72-
73-
@available(SwiftStdlib 6.2, *)
74-
public protocol SchedulableExecutor: Executor where Self.AsSchedulable == Self {
52+
public protocol SchedulableExecutor: Executor {
7553

7654
#if !$Embedded
7755

@@ -123,17 +101,13 @@ public protocol SchedulableExecutor: Executor where Self.AsSchedulable == Self {
123101
extension Executor {
124102
/// Return this executable as a SchedulableExecutor, or nil if that is
125103
/// unsupported.
104+
///
105+
/// Executors that implement SchedulableExecutor should provide their
106+
/// own copy of this method, which will allow the compiler to avoid a
107+
/// potentially expensive runtime cast.
126108
@available(SwiftStdlib 6.2, *)
127-
var asSchedulable: AsSchedulable? {
128-
#if !$Embedded
129-
if Self.self == AsSchedulable.self {
130-
return _identityCast(self, to: AsSchedulable.self)
131-
} else {
132-
return nil
133-
}
134-
#else
135-
return nil
136-
#endif
109+
var asSchedulable: SchedulableExecutor? {
110+
return self as? SchedulableExecutor
137111
}
138112
}
139113

@@ -536,71 +510,17 @@ public protocol RunLoopExecutor: Executor {
536510
@available(SwiftStdlib 6.2, *)
537511
extension RunLoopExecutor {
538512

539-
public func run(until condition: () -> Bool) throws {
513+
public func runUntil(_ condition: () -> Bool) throws {
540514
fatalError("run(until condition:) not supported on this executor")
541515
}
542516

543517
}
544518

545519

546-
/// Represents an event registered with an `EventableExecutor`.
547-
@available(SwiftStdlib 6.2, *)
548-
public struct ExecutorEvent: Identifiable, Comparable, Sendable {
549-
public typealias ID = Int
550-
551-
public var id: Self.ID
552-
553-
public init(id: Self.ID) {
554-
self.id = id
555-
}
556-
557-
public static func < (lhs: Self, rhs: Self) -> Bool {
558-
return lhs.id < rhs.id
559-
}
560-
public static func == (lhs: Self, rhs: Self) -> Bool {
561-
return lhs.id == rhs.id
562-
}
563-
}
564-
565-
566-
/// An executor that has support for coalesced events.
567-
@available(SwiftStdlib 6.2, *)
568-
public protocol EventableExecutor {
569-
570-
/// Register a new event with a given handler.
571-
///
572-
/// Notifying the executor of the event will cause the executor to
573-
/// execute the handler, however the executor is free to coalesce multiple
574-
/// event notifications, and is also free to execute the handler at a time
575-
/// of its choosing.
576-
///
577-
/// Parameters
578-
///
579-
/// - handler: The handler to call when the event fires.
580-
///
581-
/// Returns a new opaque `Event`.
582-
func registerEvent(handler: @escaping @Sendable () -> ()) -> ExecutorEvent
583-
584-
/// Deregister the given event.
585-
///
586-
/// After this function returns, there will be no further executions of the
587-
/// handler for the given event.
588-
func deregister(event: ExecutorEvent)
589-
590-
/// Notify the executor of an event.
591-
///
592-
/// This will trigger, at some future point, the execution of the associated
593-
/// event handler. Prior to that time, multiple calls to `notify` may be
594-
/// coalesced and result in a single invocation of the event handler.
595-
func notify(event: ExecutorEvent)
596-
597-
}
598-
599-
600520
/// The main executor must conform to these three protocols; we have to
601521
/// make this a protocol for compatibility with Embedded Swift.
602522
@available(SwiftStdlib 6.2, *)
603-
public protocol MainExecutor: RunLoopExecutor, SerialExecutor, EventableExecutor {
523+
public protocol MainExecutor: RunLoopExecutor, SerialExecutor {
604524
}
605525

606526

@@ -719,6 +639,9 @@ extension Task where Success == Never, Failure == Never {
719639
let schedulable = taskExecutor.asSchedulable {
720640
return schedulable
721641
}
642+
if let schedulable = defaultExecutor.asSchedulable {
643+
return schedulable
644+
}
722645
return nil
723646
}
724647
}

stdlib/public/Concurrency/PlatformExecutorEmbedded.swift

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,12 @@ public final class EmbeddedMainExecutor: MainExecutor, @unchecked Sendable {
3434
public func run() throws {
3535
}
3636

37-
public func run(until condition: () -> Bool) throws {
37+
public func runUntil(_ condition: () -> Bool) throws {
3838
}
3939

4040
public func stop() {
4141
}
4242

43-
public func registerEvent(handler: @escaping () -> ()) -> ExecutorEvent {
44-
return ExecutorEvent(id: 0)
45-
}
46-
47-
public func deregister(event: ExecutorEvent) {
48-
}
49-
50-
public func notify(event: ExecutorEvent) {
51-
}
52-
5343
}
5444

5545
// .. Platform Task Executor ...................................................

stdlib/public/Concurrency/PlatformExecutorNone.swift

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,6 @@ public class PlatformMainExecutor: MainExecutor, @unchecked Sendable {
3232
fatalError("There is no main executor implementation for this platform")
3333
}
3434

35-
public func registerEvent(handler: @escaping () -> ()) -> ExecutorEvent {
36-
fatalError("There is no main executor implementation for this platform")
37-
}
38-
39-
public func deregister(event: ExecutorEvent) {
40-
fatalError("There is no main executor implementation for this platform")
41-
}
42-
43-
public func notify(event: ExecutorEvent) {
44-
fatalError("There is no main executor implementation for this platform")
45-
}
46-
4735
}
4836

4937
// .. Platform Default Executor ................................................

stdlib/public/Concurrency/TaskSleep.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ extension Task where Success == Never, Failure == Never {
3030

3131
if #available(SwiftStdlib 6.2, *) {
3232
let executor = Task.currentSchedulableExecutor
33-
?? Task.defaultExecutor.asSchdulable
34-
3533
#if !$Embedded
3634
executor!.enqueue(ExecutorJob(context: job),
3735
after: .nanoseconds(duration),
@@ -272,7 +270,6 @@ extension Task where Success == Never, Failure == Never {
272270

273271
if #available(SwiftStdlib 6.2, *) {
274272
let executor = Task.currentSchedulableExecutor
275-
?? Task.defaultExecutor.asSchedulable
276273
let job = ExecutorJob(context: Builtin.convertTaskToJob(sleepTask))
277274
#if !$Embedded
278275
executor!.enqueue(job,

stdlib/public/Concurrency/TaskSleepDuration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension Task where Success == Never, Failure == Never {
5555
}
5656

5757
if #available(SwiftStdlib 6.2, *) {
58-
let executor = Task.currentSchdulableExecutor ?? Task.defaultExecutor.asSchedulable
58+
let executor = Task.currentSchedulableExecutor
5959
let job = ExecutorJob(context: Builtin.convertTaskToJob(sleepTask))
6060

6161
#if !$Embedded

test/Concurrency/Runtime/custom_main_executor.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,6 @@ final class SimpleMainExecutor: MainExecutor, @unchecked Sendable {
5959
func stop() {
6060
shouldStop = true
6161
}
62-
63-
func registerEvent(handler: @escaping @Sendable () -> ()) -> ExecutorEvent {
64-
return ExecutorEvent(id: 0)
65-
}
66-
67-
func deregister(event: ExecutorEvent) {
68-
}
69-
70-
func notify(event: ExecutorEvent) {
71-
}
7262
}
7363

7464
@available(SwiftStdlib 6.2, *)

test/Concurrency/Runtime/sleep_executor.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ actor MyActor {
2020
}
2121

2222
@available(SwiftStdlib 6.2, *)
23-
final class TestExecutor: TaskExecutor, SchedulableExecutor @unchecked Sendable {
23+
final class TestExecutor: TaskExecutor, SchedulableExecutor, @unchecked Sendable {
24+
var asSchedulable: SchedulableExecutor? {
25+
return self
26+
}
27+
2428
public func enqueue(_ _job: consuming ExecutorJob) {
2529
let job = UnownedJob(_job)
2630
DispatchQueue.main.async {

0 commit comments

Comments
 (0)