Skip to content

Commit f0fe850

Browse files
committed
move to DiscardingTaskGroup
1 parent 464c7b3 commit f0fe850

File tree

11 files changed

+431
-214
lines changed

11 files changed

+431
-214
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ bool swift_taskGroup_isDiscardingResults(TaskGroup *group);
307307
/// \code
308308
/// func swift_taskGroup_waitAll(
309309
/// waitingTask: Builtin.NativeObject, // current task
310-
/// group: Builtin.RawPointer,
311-
/// childFailureCancelsGroup: Bool
310+
/// group: Builtin.RawPointer
312311
/// ) async throws
313312
/// \endcode
314313
SWIFT_EXPORT_FROM(swift_Concurrency)
@@ -317,7 +316,6 @@ bool swift_taskGroup_isDiscardingResults(TaskGroup *group);
317316
OpaqueValue *resultPointer,
318317
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
319318
TaskGroup *group,
320-
bool childFailureCancelsGroup,
321319
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
322320
AsyncContext *callContext);
323321

lib/IRGen/GenBuiltin.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,11 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
287287
if (Builtin.ID == BuiltinValueKind::CreateTaskGroupWithFlags) {
288288
auto groupFlags = args.claimNext();
289289
// Claim the remaining metadata pointer.
290-
(void)args.claimNext();
290+
if (args.size() == 1) {
291+
(void)args.claimNext();
292+
} else if (args.size() > 1) {
293+
llvm_unreachable("createTaskGroupWithFlags expects 1 or 2 arguments");
294+
}
291295
out.add(emitCreateTaskGroup(IGF, substitutions, groupFlags));
292296
return;
293297
}

stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,10 +326,9 @@ OVERRIDE_TASK_GROUP(taskGroup_waitAll, void,
326326
(OpaqueValue *resultPointer,
327327
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
328328
TaskGroup *_group,
329-
bool childFailureCancelsGroup,
330329
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
331330
AsyncContext *callContext),
332-
(resultPointer, callerContext, _group, childFailureCancelsGroup,
331+
(resultPointer, callerContext, _group,
333332
resumeFn, callContext))
334333

335334
OVERRIDE_TASK_LOCAL(task_reportIllegalTaskLocalBindingWithinWithTaskGroup, void,

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
113113
TaskStatus.cpp
114114
TaskGroup.cpp
115115
TaskGroup.swift
116+
DiscardingTaskGroup.swift
116117
TaskLocal.cpp
117118
TaskLocal.swift
118119
TaskSleep.swift
Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
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+
// ==== DiscardingTaskGroup ---------------------------------------------------
17+
18+
@available(SwiftStdlib 5.8, *)
19+
@inlinable
20+
@_unsafeInheritExecutor
21+
public func withDiscardingTaskGroup<GroupResult>(
22+
returning returnType: GroupResult.Type = GroupResult.self,
23+
body: (inout DiscardingTaskGroup) async -> GroupResult
24+
) async -> GroupResult {
25+
#if compiler(>=5.5) && $BuiltinTaskGroupWithArgument
26+
let flags = taskGroupCreateFlags(
27+
discardResults: true
28+
)
29+
30+
let _group = Builtin.createTaskGroupWithFlags(flags, GroupResult.self)
31+
var group = DiscardingTaskGroup(group: _group)
32+
defer { Builtin.destroyTaskGroup(_group) }
33+
34+
let result = await body(&group)
35+
36+
try! await group.awaitAllRemainingTasks() // try!-safe, cannot throw since this is a non throwing group
37+
return result
38+
#else
39+
fatalError("Swift compiler is incompatible with this SDK version")
40+
#endif
41+
}
42+
43+
///
44+
/// - SeeAlso: ``TaskGroup``
45+
/// - SeeAlso: ``ThrowingTaskGroup``
46+
/// - SeeAlso: ``ThrowingDiscardingTaskGroup``
47+
@available(SwiftStdlib 5.8, *)
48+
@frozen
49+
public struct DiscardingTaskGroup {
50+
51+
@usableFromInline
52+
internal let _group: Builtin.RawPointer
53+
54+
// No public initializers
55+
@inlinable
56+
init(group: Builtin.RawPointer) {
57+
self._group = group
58+
}
59+
60+
/// Await all the remaining tasks on this group.
61+
///
62+
/// - Throws: The first error that was encountered by this group.
63+
@usableFromInline
64+
internal mutating func awaitAllRemainingTasks() async throws {
65+
let _: Void? = try await _taskGroupWaitAll(group: _group)
66+
}
67+
68+
@_alwaysEmitIntoClient
69+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
70+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model", renamed: "addTask(operation:)")
71+
#endif
72+
public mutating func addTask(
73+
priority: TaskPriority? = nil,
74+
operation: __owned @Sendable @escaping () async -> Void
75+
) {
76+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
77+
let flags = taskCreateFlags(
78+
priority: priority, isChildTask: true, copyTaskLocals: false,
79+
inheritContext: false, enqueueJob: false,
80+
addPendingGroupTaskUnconditionally: true
81+
)
82+
#else
83+
let flags = taskCreateFlags(
84+
priority: priority, isChildTask: true, copyTaskLocals: false,
85+
inheritContext: false, enqueueJob: true,
86+
addPendingGroupTaskUnconditionally: true
87+
)
88+
#endif
89+
90+
// Create the task in this group.
91+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
92+
}
93+
94+
@_alwaysEmitIntoClient
95+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
96+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model", renamed: "addTask(operation:)")
97+
#endif
98+
public mutating func addTaskUnlessCancelled(
99+
priority: TaskPriority? = nil,
100+
operation: __owned @Sendable @escaping () async -> Void
101+
) -> Bool {
102+
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
103+
104+
guard canAdd else {
105+
// the group is cancelled and is not accepting any new work
106+
return false
107+
}
108+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
109+
let flags = taskCreateFlags(
110+
priority: priority, isChildTask: true, copyTaskLocals: false,
111+
inheritContext: false, enqueueJob: false,
112+
addPendingGroupTaskUnconditionally: false
113+
)
114+
#else
115+
let flags = taskCreateFlags(
116+
priority: priority, isChildTask: true, copyTaskLocals: false,
117+
inheritContext: false, enqueueJob: true,
118+
addPendingGroupTaskUnconditionally: false
119+
)
120+
#endif
121+
122+
// Create the task in this group.
123+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
124+
125+
return true
126+
}
127+
128+
@_alwaysEmitIntoClient
129+
public mutating func addTask(
130+
operation: __owned @Sendable @escaping () async -> Void
131+
) {
132+
let flags = taskCreateFlags(
133+
priority: nil, isChildTask: true, copyTaskLocals: false,
134+
inheritContext: false, enqueueJob: true,
135+
addPendingGroupTaskUnconditionally: true
136+
)
137+
138+
// Create the task in this group.
139+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
140+
}
141+
142+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
143+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model", renamed: "addTaskUnlessCancelled(operation:)")
144+
#endif
145+
@_alwaysEmitIntoClient
146+
public mutating func addTaskUnlessCancelled(
147+
operation: __owned @Sendable @escaping () async -> Void
148+
) -> Bool {
149+
#if compiler(>=5.5) && $BuiltinCreateAsyncTaskInGroup
150+
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
151+
152+
guard canAdd else {
153+
// the group is cancelled and is not accepting any new work
154+
return false
155+
}
156+
157+
let flags = taskCreateFlags(
158+
priority: nil, isChildTask: true, copyTaskLocals: false,
159+
inheritContext: false, enqueueJob: true,
160+
addPendingGroupTaskUnconditionally: false
161+
)
162+
163+
// Create the task in this group.
164+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
165+
166+
return true
167+
#else
168+
fatalError("Unsupported Swift compiler")
169+
#endif
170+
}
171+
172+
public var isEmpty: Bool {
173+
_taskGroupIsEmpty(_group)
174+
}
175+
176+
public func cancelAll() {
177+
_taskGroupCancelAll(group: _group)
178+
}
179+
180+
public var isCancelled: Bool {
181+
return _taskGroupIsCancelled(group: _group)
182+
}
183+
}
184+
185+
@available(SwiftStdlib 5.8, *)
186+
@available(*, unavailable)
187+
extension DiscardingTaskGroup: Sendable { }
188+
189+
// ==== ThrowingDiscardingTaskGroup -------------------------------------------
190+
191+
@available(SwiftStdlib 5.8, *)
192+
@inlinable
193+
@_unsafeInheritExecutor
194+
public func withThrowingDiscardingTaskGroup<GroupResult>(
195+
returning returnType: GroupResult.Type = GroupResult.self,
196+
body: (inout ThrowingDiscardingTaskGroup<Error>) async throws -> GroupResult
197+
) async throws -> GroupResult {
198+
#if compiler(>=5.5) && $BuiltinTaskGroupWithArgument
199+
let flags = taskGroupCreateFlags(
200+
discardResults: true
201+
)
202+
203+
let _group = Builtin.createTaskGroupWithFlags(flags, GroupResult.self)
204+
var group = ThrowingDiscardingTaskGroup<Error>(group: _group)
205+
defer { Builtin.destroyTaskGroup(_group) }
206+
207+
let result: GroupResult
208+
do {
209+
result = try await body(&group)
210+
} catch {
211+
group.cancelAll()
212+
213+
try await group.awaitAllRemainingTasks()
214+
215+
throw error
216+
}
217+
218+
try await group.awaitAllRemainingTasks()
219+
220+
return result
221+
#else
222+
fatalError("Swift compiler is incompatible with this SDK version")
223+
#endif
224+
}
225+
226+
@available(SwiftStdlib 5.8, *)
227+
@frozen
228+
public struct ThrowingDiscardingTaskGroup<Failure: Error> {
229+
230+
@usableFromInline
231+
internal let _group: Builtin.RawPointer
232+
233+
// No public initializers
234+
@inlinable
235+
init(group: Builtin.RawPointer) {
236+
self._group = group
237+
}
238+
239+
/// Await all the remaining tasks on this group.
240+
@usableFromInline
241+
internal mutating func awaitAllRemainingTasks() async throws {
242+
let _: Void? = try await _taskGroupWaitAll(group: _group)
243+
}
244+
245+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
246+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model", renamed: "addTask(operation:)")
247+
#endif
248+
@_alwaysEmitIntoClient
249+
public mutating func addTask(
250+
priority: TaskPriority? = nil,
251+
operation: __owned @Sendable @escaping () async throws -> Void
252+
) {
253+
#if compiler(>=5.5) && $BuiltinCreateAsyncTaskInGroup
254+
let flags = taskCreateFlags(
255+
priority: priority, isChildTask: true, copyTaskLocals: false,
256+
inheritContext: false, enqueueJob: true,
257+
addPendingGroupTaskUnconditionally: true
258+
)
259+
260+
// Create the task in this group.
261+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
262+
#else
263+
fatalError("Unsupported Swift compiler")
264+
#endif
265+
}
266+
267+
#if SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
268+
@available(*, unavailable, message: "Unavailable in task-to-thread concurrency model", renamed: "addTask(operation:)")
269+
#endif
270+
@_alwaysEmitIntoClient
271+
public mutating func addTaskUnlessCancelled(
272+
priority: TaskPriority? = nil,
273+
operation: __owned @Sendable @escaping () async throws -> Void
274+
) -> Bool {
275+
#if compiler(>=5.5) && $BuiltinCreateAsyncTaskInGroup
276+
let canAdd = _taskGroupAddPendingTask(group: _group, unconditionally: false)
277+
278+
guard canAdd else {
279+
// the group is cancelled and is not accepting any new work
280+
return false
281+
}
282+
283+
let flags = taskCreateFlags(
284+
priority: priority, isChildTask: true, copyTaskLocals: false,
285+
inheritContext: false, enqueueJob: true,
286+
addPendingGroupTaskUnconditionally: false
287+
)
288+
289+
// Create the task in this group.
290+
_ = Builtin.createAsyncTaskInGroup(flags, _group, operation)
291+
292+
return true
293+
#else
294+
fatalError("Unsupported Swift compiler")
295+
#endif
296+
}
297+
298+
public var isEmpty: Bool {
299+
_taskGroupIsEmpty(_group)
300+
}
301+
302+
public func cancelAll() {
303+
_taskGroupCancelAll(group: _group)
304+
}
305+
306+
public var isCancelled: Bool {
307+
return _taskGroupIsCancelled(group: _group)
308+
}
309+
}
310+
311+
@available(SwiftStdlib 5.8, *)
312+
@available(*, unavailable)
313+
extension ThrowingDiscardingTaskGroup: Sendable { }
314+
315+
// ==== -----------------------------------------------------------------------
316+
// MARK: Runtime functions
317+
318+
/// Always returns `nil`.
319+
@available(SwiftStdlib 5.8, *)
320+
@usableFromInline
321+
@discardableResult
322+
@_silgen_name("swift_taskGroup_waitAll")
323+
func _taskGroupWaitAll<T>(
324+
group: Builtin.RawPointer
325+
) async throws -> T?
326+
327+
@available(SwiftStdlib 5.8, *) // FIXME: remove
328+
@_silgen_name("swift_taskGroup_isDiscardingResults")
329+
func _taskGroupIsDiscardingResults(group: Builtin.RawPointer) -> Bool

0 commit comments

Comments
 (0)