diff --git a/Runtimes/Core/Concurrency/CMakeLists.txt b/Runtimes/Core/Concurrency/CMakeLists.txt index 2ce834ee88a5d..0f9b86697c144 100644 --- a/Runtimes/Core/Concurrency/CMakeLists.txt +++ b/Runtimes/Core/Concurrency/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(swift_Concurrency ConcurrencyHooks.cpp EmbeddedSupport.cpp Error.cpp + ExecutorBridge.cpp ExecutorChecks.cpp GlobalExecutor.cpp Setup.cpp @@ -47,6 +48,7 @@ add_library(swift_Concurrency CheckedContinuation.swift Clock.swift ContinuousClock.swift + CooperativeExecutor.swift Deque/_DequeBuffer.swift Deque/_DequeBufferHeader.swift Deque/_DequeSlot.swift @@ -67,19 +69,27 @@ add_library(swift_Concurrency Deque/Deque+UnsafeHandle.swift Deque/UnsafeMutableBufferPointer+Utilities.swift DiscardingTaskGroup.swift + DummyExecutor.swift Errors.swift Executor.swift ExecutorAssertions.swift + ExecutorBridge.swift GlobalActor.swift GlobalConcurrentExecutor.swift MainActor.swift PartialAsyncTask.swift + PlatformExecutorDarwin.swift + PlatformExecutorLinux.swift + PlatformExecutorWindows.swift + PriorityQueue.swift SourceCompatibilityShims.swift SuspendingClock.swift Task.swift + Task+PriorityEscalation.swift Task+TaskExecutor.swift TaskCancellation.swift TaskGroup.swift + TaskGroup+Embedded.swift TaskLocal.swift TaskSleep.swift TaskSleepDuration.swift diff --git a/Runtimes/Core/Concurrency/dispatch.cmake b/Runtimes/Core/Concurrency/dispatch.cmake index d0f1adc700999..4d04b582a3b4c 100644 --- a/Runtimes/Core/Concurrency/dispatch.cmake +++ b/Runtimes/Core/Concurrency/dispatch.cmake @@ -2,7 +2,10 @@ find_package(dispatch QUIET REQUIRED) target_sources(swift_Concurrency PRIVATE - DispatchGlobalExecutor.cpp) + DispatchGlobalExecutor.cpp + DispatchExecutor.swift + CFExecutor.swift + ExecutorImpl.swift) target_compile_definitions(swift_Concurrency PRIVATE $<$:-DSWIFT_CONCURRENCY_USES_DISPATCH=1>) target_compile_options(swift_Concurrency PRIVATE diff --git a/Runtimes/Core/Concurrency/hooked.cmake b/Runtimes/Core/Concurrency/hooked.cmake index 009723d792bd6..2a420147f6bbc 100644 --- a/Runtimes/Core/Concurrency/hooked.cmake +++ b/Runtimes/Core/Concurrency/hooked.cmake @@ -1,2 +1,3 @@ target_sources(swift_Concurrency PRIVATE - NonDispatchGlobalExecutor.cpp) + ExecutorImpl.swift + PlatformExecutorNone.swift) diff --git a/Runtimes/Core/Concurrency/none.cmake b/Runtimes/Core/Concurrency/none.cmake index 009723d792bd6..2a420147f6bbc 100644 --- a/Runtimes/Core/Concurrency/none.cmake +++ b/Runtimes/Core/Concurrency/none.cmake @@ -1,2 +1,3 @@ target_sources(swift_Concurrency PRIVATE - NonDispatchGlobalExecutor.cpp) + ExecutorImpl.swift + PlatformExecutorNone.swift) diff --git a/Runtimes/Core/Concurrency/singlethreaded.cmake b/Runtimes/Core/Concurrency/singlethreaded.cmake index 0c4f1109cefee..052ae5348783a 100644 --- a/Runtimes/Core/Concurrency/singlethreaded.cmake +++ b/Runtimes/Core/Concurrency/singlethreaded.cmake @@ -1,2 +1,3 @@ target_sources(swift_Concurrency PRIVATE - CooperativeGlobalExecutor.cpp) + ExecutorImpl.swift + PlatformExecutorCooperative.swift) diff --git a/stdlib/public/Concurrency/Executor.swift b/stdlib/public/Concurrency/Executor.swift index 1c90ccccd83c7..9c64fecf43da4 100644 --- a/stdlib/public/Concurrency/Executor.swift +++ b/stdlib/public/Concurrency/Executor.swift @@ -36,12 +36,7 @@ public protocol Executor: AnyObject, Sendable { func enqueue(_ job: consuming ExecutorJob) #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY - #if !$Embedded && !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY - // The functions below could have been added to a separate protocol, - // but doing that would then mean doing an `as?` cast in e.g. - // enqueueOnGlobalExecutor (in ExecutorBridge.swift), which is - // undesirable from a performance perspective. - + #if !$Embedded /// `true` if this is the main executor. @available(SwiftStdlib 6.2, *) var isMainExecutor: Bool { get } @@ -125,7 +120,7 @@ extension Executor where Self: Equatable { extension Executor { - #if !$Embedded && !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY + #if !$Embedded // This defaults to `false` so that existing third-party Executor // implementations will work as expected. @available(SwiftStdlib 6.2, *) diff --git a/stdlib/public/Concurrency/ExecutorBridge.cpp b/stdlib/public/Concurrency/ExecutorBridge.cpp index 50595d7180b82..6debd5659beb8 100644 --- a/stdlib/public/Concurrency/ExecutorBridge.cpp +++ b/stdlib/public/Concurrency/ExecutorBridge.cpp @@ -27,6 +27,13 @@ void _swift_exit(int result) { exit(result); } +#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY +extern "C" SWIFT_CC(swift) +SerialExecutorRef swift_getMainExecutor() { + return SerialExecutorRef::generic(); +} +#endif + extern "C" SWIFT_CC(swift) void _swift_task_checkIsolatedSwift( HeapObject *executor, diff --git a/stdlib/public/Concurrency/ExecutorBridge.swift b/stdlib/public/Concurrency/ExecutorBridge.swift index 1caa4e31aee57..9301de71d43e3 100644 --- a/stdlib/public/Concurrency/ExecutorBridge.swift +++ b/stdlib/public/Concurrency/ExecutorBridge.swift @@ -21,7 +21,7 @@ import Swift @_silgen_name("_swift_exit") internal func _exit(result: CInt) -#if !$Embedded && !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY +#if !$Embedded @available(SwiftStdlib 6.2, *) @_silgen_name("_swift_task_isMainExecutorSwift") internal func _isMainExecutor(_ executor: E) -> Bool where E: SerialExecutor { @@ -79,13 +79,20 @@ internal func _jobGetExecutorPrivateData( _ job: Builtin.Job ) -> UnsafeMutableRawPointer -#if !$Embedded && !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY +#if !$Embedded +#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY @available(SwiftStdlib 6.2, *) @_silgen_name("swift_getMainExecutor") -internal func _getMainExecutor() -> any MainExecutor { +internal func _getMainExecutor() -> any SerialExecutor { return MainActor.executor } -#endif +#else +// For task-to-thread model, this is implemented in C++ +@available(SwiftStdlib 6.2, *) +@_silgen_name("swift_getMainExecutor") +internal func _getMainExecutor() -> any SerialExecutor +#endif // SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY +#endif // !$Embedded @available(SwiftStdlib 6.2, *) @_silgen_name("swift_dispatchMain") diff --git a/stdlib/public/Concurrency/ExecutorImpl.swift b/stdlib/public/Concurrency/ExecutorImpl.swift index d50aaa60e1d93..2c76075b33084 100644 --- a/stdlib/public/Concurrency/ExecutorImpl.swift +++ b/stdlib/public/Concurrency/ExecutorImpl.swift @@ -20,14 +20,16 @@ import Swift -#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_asyncMainDrainQueueImpl") internal func drainMainQueue() { + #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY try! MainActor.executor.run() _exit(result: 0) + #else + fatalError("swift_task_asyncMainDrainQueue() not supported with task-to-thread") + #endif } -#endif @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_donateThreadToGlobalExecutorUntilImpl") @@ -42,19 +44,21 @@ internal func dontateToGlobalExecutor( } } -#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_getMainExecutorImpl") internal func getMainExecutor() -> UnownedSerialExecutor { - return unsafe UnownedSerialExecutor(MainActor.executor) + return unsafe _getMainExecutor().asUnownedSerialExecutor() } @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_enqueueMainExecutorImpl") internal func enqueueOnMainExecutor(job unownedJob: UnownedJob) { + #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY MainActor.executor.enqueue(unownedJob) + #else + fatalError("swift_task_enqueueMainExecutor() not supported for task-to-thread") + #endif } -#endif @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_enqueueGlobalImpl") @@ -62,14 +66,18 @@ internal func enqueueOnGlobalExecutor(job unownedJob: UnownedJob) { Task.defaultExecutor.enqueue(unownedJob) } -#if !$Embedded && !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY +#if !$Embedded @available(SwiftStdlib 6.2, *) @_silgen_name("swift_task_enqueueGlobalWithDelayImpl") internal func enqueueOnGlobalExecutor(delay: CUnsignedLongLong, job unownedJob: UnownedJob) { + #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY Task.defaultExecutor.asSchedulable!.enqueue(ExecutorJob(unownedJob), after: .nanoseconds(delay), clock: .continuous) + #else + fatalError("swift_task_enqueueGlobalWithDelay() not supported for task-to-thread") + #endif } @available(SwiftStdlib 6.2, *) @@ -80,6 +88,7 @@ internal func enqueueOnGlobalExecutor(seconds: CLongLong, leewayNanoseconds: CLongLong, clock: CInt, job unownedJob: UnownedJob) { + #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY let delay = Duration.seconds(seconds) + Duration.nanoseconds(nanoseconds) let leeway = Duration.seconds(leewaySeconds) + Duration.nanoseconds(leewayNanoseconds) switch clock { @@ -96,5 +105,8 @@ internal func enqueueOnGlobalExecutor(seconds: CLongLong, default: fatalError("Unknown clock ID \(clock)") } + #else + fatalError("swift_task_enqueueGlobalWithDeadline() not supported for task-to-thread") + #endif } #endif