Skip to content

Commit e843a24

Browse files
committed
[Concurrency] Fix issue with using Dispatch queues as executors.
We were failing to switch executors to Dispatch queues, where those were being used as executors, which caused a variety of unusual symptoms. rdar://150310927
1 parent 6b4710e commit e843a24

File tree

4 files changed

+36
-1
lines changed

4 files changed

+36
-1
lines changed

stdlib/public/Concurrency/Executor.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,26 @@ extension SerialExecutor {
382382
#endif
383383
}
384384

385+
#if SWIFT_CONCURRENCY_USES_DISPATCH
386+
@available(SwiftStdlib 6.2, *)
387+
private var _dispatchQueue: OpaquePointer? {
388+
return _getDispatchQueueForExecutor(self.asUnownedSerialExecutor())
389+
}
390+
#endif
391+
385392
@available(SwiftStdlib 6.2, *)
386393
internal func _isSameExecutor(_ rhs: some SerialExecutor) -> Bool {
387394
if rhs === self {
388395
return true
389396
}
397+
#if SWIFT_CONCURRENCY_USES_DISPATCH
398+
if let rhsQueue = rhs._dispatchQueue {
399+
if let ourQueue = _dispatchQueue, ourQueue == rhsQueue {
400+
return true
401+
}
402+
return false
403+
}
404+
#endif
390405
if let rhs = rhs as? Self {
391406
return isSameExclusiveExecutionContext(other: rhs)
392407
}

stdlib/public/Concurrency/ExecutorBridge.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "Error.h"
2020
#include "ExecutorBridge.h"
21+
#include "TaskPrivate.h"
2122

2223
using namespace swift;
2324

@@ -73,6 +74,15 @@ extern "C" SWIFT_CC(swift)
7374
void swift_dispatchAssertMainQueue() {
7475
dispatch_assert_queue(dispatch_get_main_queue());
7576
}
76-
#endif // SWIFT_CONCURRENCY_ENABLE_DISPATCH
77+
78+
extern "C" SWIFT_CC(swift)
79+
void *swift_getDispatchQueueForExecutor(SerialExecutorRef executor) {
80+
if (executor.getRawImplementation() == (uintptr_t)_swift_task_getDispatchQueueSerialExecutorWitnessTable()) {
81+
return executor.getIdentity();
82+
}
83+
return nullptr;
84+
}
85+
86+
#endif // SWIFT_CONCURRENCY_USES_DISPATCH
7787

7888
#pragma clang diagnostic pop

stdlib/public/Concurrency/ExecutorBridge.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,8 @@ internal func _dispatchAssertMainQueue()
130130

131131
@_silgen_name("swift_createDefaultExecutorsOnce")
132132
func _createDefaultExecutorsOnce()
133+
134+
@_silgen_name("swift_getDispatchQueueForExecutor")
135+
internal func _getDispatchQueueForExecutor(
136+
_ executor: UnownedSerialExecutor
137+
) -> OpaquePointer?

stdlib/public/Concurrency/Task.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,11 @@ static SerialExecutorRef executorForEnqueuedJob(Job *job) {
382382
return swift_task_getMainExecutor();
383383
}
384384

385+
if (auto identity = reinterpret_cast<HeapObject *>(jobQueue)) {
386+
return SerialExecutorRef::forOrdinary(
387+
identity, _swift_task_getDispatchQueueSerialExecutorWitnessTable());
388+
}
389+
385390
return SerialExecutorRef::generic();
386391
#endif
387392
}

0 commit comments

Comments
 (0)