Skip to content

Commit 1dec00a

Browse files
authored
[TaskExecutors] Task initializer and withTaskExecutor parameter changes (swiftlang#70783)
1 parent 1843c6f commit 1dec00a

13 files changed

+352
-176
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
107107
AsyncThrowingMapSequence.swift
108108
AsyncThrowingPrefixWhileSequence.swift
109109
GlobalActor.swift
110+
GlobalConcurrentExecutor.swift
110111
MainActor.swift
111112
PartialAsyncTask.swift
112113
SourceCompatibilityShims.swift

stdlib/public/Concurrency/Executor.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ public protocol SerialExecutor: Executor {
113113
/// requirements.
114114
///
115115
/// By setting a task executor preference, either with a
116-
/// ``_withTaskExecutor(_:operation:)``, creating a task with a preference
117-
/// (`Task(_on:)`, or `group.addTask(on:)`), the task and all of its child
116+
/// ``_withTaskExecutorPreference(_:operation:)``, creating a task with a preference
117+
/// (`Task(_executorPreference:)`, or `group.addTask(executorPreference:)`), the task and all of its child
118118
/// tasks (unless a new preference is set) will be preferring to execute on
119119
/// the provided task executor.
120120
///
@@ -375,9 +375,8 @@ internal func _task_serialExecutor_getExecutorRef<E>(_ executor: E) -> Builtin.E
375375
@_unavailableInEmbedded
376376
@available(SwiftStdlib 9999, *)
377377
@_silgen_name("_task_executor_getTaskExecutorRef")
378-
internal func _task_executor_getTaskExecutorRef<E>(_ executor: E) -> Builtin.Executor
379-
where E: _TaskExecutor {
380-
return executor.asUnownedTaskExecutor().executor
378+
internal func _task_executor_getTaskExecutorRef(_ taskExecutor: any _TaskExecutor) -> Builtin.Executor {
379+
return taskExecutor.asUnownedTaskExecutor().executor
381380
}
382381

383382
// Used by the concurrency runtime
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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 _SwiftConcurrencyShims
15+
16+
// None of _TaskExecutor APIs are available in task-to-thread concurrency model.
17+
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
18+
19+
/// The global concurrent executor that is used by default for Swift Concurrency
20+
/// tasks.
21+
///
22+
/// The executor's implementation is platform dependent.
23+
/// By default it uses a fixed size pool of threads and should not be used for
24+
/// blocking operations which do not guarantee forward progress as doing so may
25+
/// prevent other tasks from being executed and render the system unresponsive.
26+
///
27+
/// You may pass this executor explicitly to a ``Task`` initializer as a task
28+
/// executor preference, in order to ensure and document that task be executed
29+
/// on the global executor, instead e.g. inheriting the enclosing actor's
30+
/// executor. Refer to ``_withTaskExecutorPreference(_:operation:)`` for a
31+
/// detailed discussion of task executor preferences.
32+
///
33+
/// Customizing the global concurrent executor is currently not supported.
34+
@available(SwiftStdlib 9999, *)
35+
nonisolated(unsafe)
36+
public var globalConcurrentExecutor: any _TaskExecutor {
37+
get {
38+
_DefaultGlobalConcurrentExecutor.shared
39+
}
40+
// TODO: introduce a set {} once we are ready to allow customizing the
41+
// default global executor. This should be done the same for main actor
42+
}
43+
44+
/// A task executor which enqueues all work on the default global concurrent
45+
/// thread pool that is used as the default executor for Swift concurrency
46+
/// tasks.
47+
@available(SwiftStdlib 9999, *)
48+
internal final class _DefaultGlobalConcurrentExecutor: _TaskExecutor {
49+
public static let shared: _DefaultGlobalConcurrentExecutor = .init()
50+
51+
private init() {}
52+
53+
public func enqueue(_ job: consuming ExecutorJob) {
54+
_enqueueJobGlobal(job.context)
55+
}
56+
57+
public func asUnownedTaskExecutor() {
58+
// The "default global concurrent executor" is simply the "undefined" one.
59+
// We represent it as the `(0, 0)` ExecutorRef and it is handled properly
60+
// by the runtime, without having to call through to the
61+
// `_DefaultGlobalConcurrentExecutor` declared in Swift.
62+
UnownedTaskExecutor(_getUndefinedTaskExecutor())
63+
}
64+
}
65+
66+
#endif

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public struct UnownedJob: Sendable {
121121
@available(SwiftStdlib 9999, *)
122122
@_alwaysEmitIntoClient
123123
@inlinable
124-
public func runSynchronously(isolated serialExecutor: UnownedSerialExecutor,
124+
public func runSynchronously(isolatedTo serialExecutor: UnownedSerialExecutor,
125125
taskExecutor: UnownedTaskExecutor) {
126126
_swiftJobRunOnTaskExecutor(self, serialExecutor, taskExecutor)
127127
}

0 commit comments

Comments
 (0)