Skip to content

Commit f3eff4a

Browse files
authored
Merge pull request #36938 from ktoso/wip-cleaner-abi-asynclet
[Concurrency] Store child record when async let child task spawned
2 parents b3746e6 + 64da78c commit f3eff4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+885
-162
lines changed

include/swift/ABI/AsyncLet.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- AsyncLet.h - ABI structures for async let -00-----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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+
// Swift ABI describing task groups.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_ABI_TASK_ASYNC_LET_H
18+
#define SWIFT_ABI_TASK_ASYNC_LET_H
19+
20+
#include "swift/ABI/Task.h"
21+
#include "swift/ABI/HeapObject.h"
22+
#include "swift/Runtime/Concurrency.h"
23+
#include "swift/Runtime/Config.h"
24+
#include "swift/Basic/RelativePointer.h"
25+
#include "swift/Basic/STLExtras.h"
26+
27+
namespace swift {
28+
29+
/// Represents an in-flight `async let`, i.e. the Task that is computing the
30+
/// result of the async let, along with the awaited status and other metadata.
31+
class alignas(Alignment_AsyncLet) AsyncLet {
32+
public:
33+
// These constructors do not initialize the AsyncLet instance, and the
34+
// destructor does not destroy the AsyncLet instance; you must call
35+
// swift_asyncLet_{start,end} yourself.
36+
constexpr AsyncLet()
37+
: PrivateData{} {}
38+
39+
// FIXME: not sure how many words we should reserve
40+
void *PrivateData[NumWords_AsyncLet];
41+
42+
// TODO: we could offer a "was awaited on" check here
43+
44+
/// Returns the child task that is associated with this async let.
45+
/// The tasks completion is used to fulfil the value represented by this async let.
46+
AsyncTask *getTask() const;
47+
48+
};
49+
50+
} // end namespace swift
51+
52+
#endif // SWIFT_ABI_TASK_ASYNC_LET_H

include/swift/ABI/MetadataValues.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ enum {
4949

5050
/// The number of words in a task group.
5151
NumWords_TaskGroup = 32,
52+
53+
/// The number of words in an AsyncLet (flags + task pointer)
54+
NumWords_AsyncLet = 8, // TODO: not sure how much is enough, these likely could be pretty small
5255
};
5356

5457
struct InProcess;
@@ -127,6 +130,9 @@ const size_t Alignment_DefaultActor = MaximumAlignment;
127130
/// The alignment of a TaskGroup.
128131
const size_t Alignment_TaskGroup = MaximumAlignment;
129132

133+
/// The alignment of an AsyncLet.
134+
const size_t Alignment_AsyncLet = MaximumAlignment;
135+
130136
/// Flags stored in the value-witness table.
131137
template <typename int_type>
132138
class TargetValueWitnessFlags {

include/swift/ABI/TaskGroup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ namespace swift {
2929
/// The task group is responsible for maintaining dynamically created child tasks.
3030
class alignas(Alignment_TaskGroup) TaskGroup {
3131
public:
32-
// These constructors do not initialize the actor instance, and the
33-
// destructor does not destroy the actor instance; you must call
32+
// These constructors do not initialize the group instance, and the
33+
// destructor does not destroy the group instance; you must call
3434
// swift_taskGroup_{initialize,destroy} yourself.
3535
constexpr TaskGroup()
3636
: PrivateData{} {}
@@ -43,4 +43,4 @@ class alignas(Alignment_TaskGroup) TaskGroup {
4343

4444
} // end namespace swift
4545

46-
#endif
46+
#endif // SWIFT_ABI_TASK_GROUP_H

include/swift/AST/Builtins.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,19 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentAsyncTask, "getCurrentAsyncTask", "
782782
/// Cancel the given asynchronous task.
783783
BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Special)
784784

785+
/// startAsyncLet()<T>: (
786+
/// __owned @Sendable @escaping () async throws -> T
787+
/// ) -> Builtin.RawPointer
788+
///
789+
/// Create, initialize and start a new async-let and associated task.
790+
/// Returns an AsyncLet* that must be passed to endAsyncLet for destruction.
791+
BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)
792+
793+
/// asyncLetEnd(): (Builtin.RawPointer) -> Void
794+
///
795+
/// Ends and destroys an async-let.
796+
BUILTIN_MISC_OPERATION_WITH_SILGEN(EndAsyncLet, "endAsyncLet", "", Special)
797+
785798
/// createAsyncTaskFuture(): (
786799
/// Int, Builtin.NativeObject?, @escaping () async throws -> T
787800
/// ) -> Builtin.NativeObject

include/swift/Runtime/Concurrency.h

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_RUNTIME_CONCURRENCY_H
1919

2020
#include "swift/ABI/TaskGroup.h"
21+
#include "swift/ABI/AsyncLet.h"
2122
#include "swift/ABI/TaskStatus.h"
2223

2324
#pragma clang diagnostic push
@@ -49,15 +50,17 @@ using FutureAsyncSignature =
4950
/// closure.
5051
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
5152
AsyncTaskAndContext swift_task_create_future(
52-
JobFlags flags, const Metadata *futureResultType,
53+
JobFlags flags,
54+
const Metadata *futureResultType,
5355
void *closureEntryPoint,
5456
HeapObject * /* +1 */ closureContext);
5557

5658
/// Create a task object with a future which will run the given
5759
/// function.
5860
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
5961
AsyncTaskAndContext swift_task_create_future_f(
60-
JobFlags flags, const Metadata *futureResultType,
62+
JobFlags flags,
63+
const Metadata *futureResultType,
6164
FutureAsyncSignature::FunctionType *function,
6265
size_t initialContextSize);
6366

@@ -74,7 +77,8 @@ AsyncTaskAndContext swift_task_create_group_future(
7477
/// function, and offer its result to the task group
7578
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
7679
AsyncTaskAndContext swift_task_create_group_future_f(
77-
JobFlags flags, TaskGroup *group,
80+
JobFlags flags,
81+
TaskGroup *group,
7882
const Metadata *futureResultType,
7983
FutureAsyncSignature::FunctionType *function,
8084
size_t initialContextSize);
@@ -169,7 +173,7 @@ SWIFT_CC(swiftasync)
169173
/// \code
170174
/// func swift_taskGroup_wait_next_throwing(
171175
/// waitingTask: Builtin.NativeObject, // current task
172-
/// group: UnsafeRawPointer
176+
/// group: Builtin.RawPointer
173177
/// ) async -> T
174178
/// \endcode
175179
SWIFT_EXPORT_FROM(swift_Concurrency)
@@ -184,8 +188,7 @@ void swift_taskGroup_wait_next_throwing(
184188
/// Its Swift signature is
185189
///
186190
/// \code
187-
/// func swift_taskGroup_initialize(group: Builtin.RawPointer
188-
/// )
191+
/// func swift_taskGroup_initialize(group: Builtin.RawPointer)
189192
/// \endcode
190193
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
191194
void swift_taskGroup_initialize(TaskGroup *group);
@@ -202,7 +205,6 @@ void swift_taskGroup_initialize(TaskGroup *group);
202205
/// \code
203206
/// func swift_taskGroup_attachChild(
204207
/// group: Builtin.RawPointer,
205-
/// parent: Builtin.NativeObject,
206208
/// child: Builtin.NativeObject
207209
/// )
208210
/// \endcode
@@ -214,7 +216,7 @@ void swift_taskGroup_attachChild(TaskGroup *group, AsyncTask *child);
214216
/// This function MUST be called from the AsyncTask running the task group.
215217
///
216218
/// \code
217-
/// func swift_taskGroup_destroy(_ group: UnsafeRawPointer)
219+
/// func swift_taskGroup_destroy(_ group: Builtin.RawPointer)
218220
/// \endcode
219221
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
220222
void swift_taskGroup_destroy(TaskGroup *group);
@@ -244,7 +246,7 @@ bool swift_taskGroup_addPending(TaskGroup *group, bool unconditionally);
244246
/// Its Swift signature is
245247
///
246248
/// \code
247-
/// func swift_taskGroup_cancelAll(group: UnsafeRawPointer)
249+
/// func swift_taskGroup_cancelAll(group: Builtin.RawPointer)
248250
/// \endcode
249251
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
250252
void swift_taskGroup_cancelAll(TaskGroup *group);
@@ -257,7 +259,7 @@ void swift_taskGroup_cancelAll(TaskGroup *group);
257259
/// This can be called from any thread. Its Swift signature is
258260
///
259261
/// \code
260-
/// func swift_taskGroup_isCancelled(group: UnsafeRawPointer)
262+
/// func swift_taskGroup_isCancelled(group: Builtin.RawPointer)
261263
/// \endcode
262264
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
263265
bool swift_taskGroup_isCancelled(TaskGroup *group);
@@ -274,6 +276,63 @@ bool swift_taskGroup_isCancelled(TaskGroup *group);
274276
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
275277
bool swift_taskGroup_isEmpty(TaskGroup *group);
276278

279+
/// Its Swift signature is
280+
///
281+
/// \code
282+
/// func swift_asyncLet_start<T>(
283+
/// _ alet: Builtin.RawPointer,
284+
/// operation: __owned @Sendable @escaping () async throws -> T
285+
/// )
286+
/// \endcode
287+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
288+
void swift_asyncLet_start(
289+
AsyncLet *alet,
290+
const Metadata *futureResultType,
291+
void *closureEntryPoint,
292+
HeapObject * /* +1 */ closureContext);
293+
294+
/// This matches the ABI of a closure `<T>(Builtin.RawPointer) async -> T`
295+
using AsyncLetWaitSignature =
296+
SWIFT_CC(swiftasync)
297+
void(OpaqueValue *,
298+
SWIFT_ASYNC_CONTEXT AsyncContext *, AsyncTask *, Metadata *);
299+
300+
/// Wait for a non-throwing async-let to complete.
301+
///
302+
/// This can be called from any thread. Its Swift signature is
303+
///
304+
/// \code
305+
/// func swift_asyncLet_wait(
306+
/// _ asyncLet: _owned Builtin.RawPointer
307+
/// ) async -> Success
308+
/// \endcode
309+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
310+
void swift_asyncLet_wait(OpaqueValue *,
311+
SWIFT_ASYNC_CONTEXT AsyncContext *,
312+
AsyncLet *, Metadata *);
313+
314+
/// Wait for a potentially-throwing async-let to complete.
315+
///
316+
/// This can be called from any thread. Its Swift signature is
317+
///
318+
/// \code
319+
/// func swift_asyncLet_wait_throwing(
320+
/// _ asyncLet: _owned Builtin.RawPointer
321+
/// ) async throws -> Success
322+
/// \endcode
323+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
324+
void swift_asyncLet_wait_throwing(OpaqueValue *,
325+
SWIFT_ASYNC_CONTEXT AsyncContext *,
326+
AsyncLet *, Metadata *);
327+
328+
/// Its Swift signature is
329+
///
330+
/// \code
331+
/// func swift_asyncLet_end(_ alet: Builtin.RawPointer)
332+
/// \endcode
333+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
334+
void swift_asyncLet_end(AsyncLet *alet);
335+
277336
/// Add a status record to a task. The record should not be
278337
/// modified while it is registered with a task.
279338
///
@@ -314,8 +373,7 @@ bool swift_task_removeStatusRecord(TaskStatusRecord *record);
314373
/// The record must be removed with by the parent invoking
315374
/// `swift_task_detachChild` when the child has completed.
316375
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
317-
ChildTaskStatusRecord*
318-
swift_task_attachChild(AsyncTask *child);
376+
ChildTaskStatusRecord* swift_task_attachChild(AsyncTask *child);
319377

320378
/// Remove a child task from the parent tracking it.
321379
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,7 +1541,8 @@ FUNCTION(TaskCreateFunc,
15411541
// AsyncTaskAndContext swift_task_create_future(
15421542
// size_t flags,
15431543
// const Metadata *futureResultType,
1544-
// void *closureEntry, HeapObject *closureContext);
1544+
// void *closureEntry,
1545+
// HeapObject *closureContext);
15451546
FUNCTION(TaskCreateFuture,
15461547
swift_task_create_future, SwiftCC,
15471548
ConcurrencyAvailability,
@@ -1553,7 +1554,8 @@ FUNCTION(TaskCreateFuture,
15531554
// AsyncTaskAndContext swift_task_create_future_f(
15541555
// size_t flags,
15551556
// const Metadata *futureResultType,
1556-
// TaskContinuationFunction *function, size_t contextSize);
1557+
// TaskContinuationFunction *function,
1558+
// size_t contextSize);
15571559
FUNCTION(TaskCreateFutureFunc,
15581560
swift_task_create_future_f, SwiftCC,
15591561
ConcurrencyAvailability,
@@ -1563,9 +1565,11 @@ FUNCTION(TaskCreateFutureFunc,
15631565
ATTRS(NoUnwind, ArgMemOnly))
15641566

15651567
// AsyncTaskAndContext swift_task_create_group_future(
1566-
// size_t flags, TaskGroup *group,
1568+
// size_t flags,
1569+
// TaskGroup *group,
15671570
// const Metadata *futureResultType,
1568-
// void *closureEntry, HeapObject *closureContext);
1571+
// void *closureEntry,
1572+
// HeapObject *closureContext);
15691573
FUNCTION(TaskCreateGroupFuture,
15701574
swift_task_create_group_future, SwiftCC,
15711575
ConcurrencyAvailability,
@@ -1576,9 +1580,11 @@ FUNCTION(TaskCreateGroupFuture,
15761580
ATTRS(NoUnwind, ArgMemOnly))
15771581

15781582
// AsyncTaskAndContext swift_task_create_group_future_f(
1579-
// size_t flags, TaskGroup *group,
1583+
// size_t flags,
1584+
// TaskGroup *group,
15801585
// const Metadata *futureResultType,
1581-
// TaskContinuationFunction *function, size_t contextSize);
1586+
// TaskContinuationFunction *function,
1587+
// size_t contextSize);
15821588
FUNCTION(TaskCreateGroupFutureFunc,
15831589
swift_task_create_group_future_f, SwiftCC,
15841590
ConcurrencyAvailability,
@@ -1672,6 +1678,31 @@ FUNCTION(DefaultActorDeallocateResilient,
16721678
ARGS(RefCountedPtrTy),
16731679
ATTRS(NoUnwind))
16741680

1681+
/// void swift_asyncLet_start(
1682+
/// AsyncLet *alet,
1683+
/// const Metadata *futureResultType,
1684+
/// void *closureEntryPoint,
1685+
/// HeapObject *closureContext
1686+
/// );
1687+
FUNCTION(AsyncLetStart,
1688+
swift_asyncLet_start, SwiftCC,
1689+
ConcurrencyAvailability,
1690+
RETURNS(VoidTy),
1691+
ARGS(SwiftAsyncLetPtrTy, // AsyncLet*, alias for Int8PtrTy
1692+
TypeMetadataPtrTy, // futureResultType
1693+
Int8PtrTy, // closureEntry
1694+
RefCountedPtrTy, // closureContext
1695+
),
1696+
ATTRS(NoUnwind, ArgMemOnly))
1697+
1698+
// void swift_asyncLet_end(AsyncLet *alet);
1699+
FUNCTION(EndAsyncLet,
1700+
swift_asyncLet_end, SwiftCC,
1701+
ConcurrencyAvailability,
1702+
RETURNS(VoidTy),
1703+
ARGS(SwiftAsyncLetPtrTy),
1704+
ATTRS(NoUnwind))
1705+
16751706
// void swift_taskGroup_initialize(TaskGroup *group);
16761707
FUNCTION(TaskGroupInitialize,
16771708
swift_taskGroup_initialize, SwiftCC,

0 commit comments

Comments
 (0)