Skip to content

Commit 9023e56

Browse files
committed
[Concurrency] Add minimal placeholders for Task and UnsafeContinuation
1 parent 39cc436 commit 9023e56

File tree

5 files changed

+132
-0
lines changed

5 files changed

+132
-0
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
1414
Actor.swift
1515
PartialAsyncTask.swift
1616
Task.cpp
17+
Task.swift
1718
TaskAlloc.cpp
1819
TaskStatus.cpp
1920
Mutex.cpp
@@ -36,6 +37,7 @@ add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I
3637
SWIFT_COMPILE_FLAGS
3738
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
3839
-parse-stdlib
40+
-Xfrontend -enable-experimental-concurrency
3941
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
4042
INSTALL_IN_COMPONENT stdlib
4143
)

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import Swift
1414
@_implementationOnly import _SwiftConcurrencyShims
1515

16+
/// A partial task is a unit of scheduleable work.
1617
public struct PartialAsyncTask {
1718
private var context: UnsafeMutablePointer<_SwiftContext>
1819

stdlib/public/Concurrency/Task.swift

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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+
// ==== Task -------------------------------------------------------------------
17+
18+
/// An asynchronous task (just "Task" hereafter) is the analogue of a thread for
19+
/// asynchronous functions. All asynchronous functions run as part of some task.
20+
///
21+
/// A task's execution can be seen as a series of periods where the task was
22+
/// running. Each such period ends at a suspension point or -- finally -- the
23+
/// completion of the task.
24+
///
25+
/// These partial periods towards the task's completion are `PartialAsyncTask`.
26+
/// Partial tasks are generally not interacted with by end-users directly,
27+
/// unless implementing a scheduler.
28+
public struct Task {
29+
}
30+
31+
// ==== UnsafeContinuation -----------------------------------------------------
32+
33+
extension Task {
34+
public struct UnsafeContinuation<T> {
35+
/// Return a value into the continuation and make the task schedulable.
36+
///
37+
/// The task will never run synchronously, even if the task does not
38+
/// need to be resumed on a specific executor.
39+
///
40+
/// This is appropriate when the caller is something "busy", like an event
41+
/// loop, and doesn't want to be potentially delayed by arbitrary work.
42+
public func resume(returning: T) {
43+
fatalError("\(#function) not implemented yet.")
44+
}
45+
}
46+
47+
public struct UnsafeThrowingContinuation<T, E: Error> {
48+
/// Return a value into the continuation and make the task schedulable.
49+
///
50+
/// The task will never run synchronously, even if the task does not
51+
/// need to be resumed on a specific executor.
52+
///
53+
/// This is appropriate when the caller is something "busy", like an event
54+
/// loop, and doesn't want to be potentially delayed by arbitrary work.
55+
public func resume(returning: T) {
56+
fatalError("\(#function) not implemented yet.")
57+
}
58+
59+
/// Resume the continuation with an error and make the task schedulable.
60+
///
61+
/// The task will never run synchronously, even if the task does not
62+
/// need to be resumed on a specific executor.
63+
///
64+
/// This is appropriate when the caller is something "busy", like an event
65+
/// loop, and doesn't want to be potentially delayed by arbitrary work.
66+
public func resume(throwing: E) {
67+
fatalError("\(#function) not implemented yet.")
68+
}
69+
}
70+
71+
/// The operation functions must resume the continuation *exactly once*.
72+
///
73+
/// The continuation will not begin executing until the operation function returns.
74+
public static func withUnsafeContinuation<T>(
75+
operation: (UnsafeContinuation<T>) -> Void
76+
) async -> T {
77+
fatalError("\(#function) not implemented yet.")
78+
}
79+
80+
/// The operation functions must resume the continuation *exactly once*.
81+
///
82+
/// The continuation will not begin executing until the operation function returns.
83+
public static func withUnsafeThrowingContinuation<T>(
84+
operation: (UnsafeThrowingContinuation<T, Error>) -> Void
85+
) async throws -> T {
86+
fatalError("\(#function) not implemented yet.")
87+
}
88+
}

test/Concurrency/actor_isolation.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ var mutableGlobal: String = "can't touch this" // expected-note 2{{var declared
77
func globalFunc() { }
88
func acceptClosure<T>(_: () -> T) { }
99
func acceptEscapingClosure<T>(_: @escaping () -> T) { }
10+
func acceptEscapingClosure<T>(_: (String) -> ()) async -> T? { nil }
1011

1112
func acceptAsyncClosure<T>(_: () async -> T) { }
1213
func acceptEscapingAsyncClosure<T>(_: @escaping () async -> T) { }
1314

15+
1416
// ----------------------------------------------------------------------
1517
// Actor state isolation restrictions
1618
// ----------------------------------------------------------------------

test/Concurrency/async_tasks.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
2+
// REQUIRES: concurrency
3+
4+
func someAsyncFunc() async -> String { "" }
5+
struct MyError: Error {}
6+
7+
// non-async function with "weird shape" representing some API that has not adopted
8+
// swift concurrency yet, but we want to call it from an async function and make it
9+
// play nice with the rest of the system.
10+
func someManyCallbacksFunction(
11+
calledSometimes: () -> (),
12+
otherwiseThisIsCalled: () -> (),
13+
calledOnError: (Error) -> ()
14+
) { }
15+
16+
func test_unsafeContinuations() async {
17+
// the closure should not allow async operations;
18+
// after all: if you have async code, just call it directly, without the unsafe continuation
19+
let _: String = Task.withUnsafeContinuation { continuation in // expected-error{{cannot convert value of type '(_) async -> ()' to expected argument type '(Task.UnsafeContinuation<String>) -> Void'}}
20+
let s = await someAsyncFunc() // rdar://70610141 for getting a better error message here
21+
continuation.resume(returning: s)
22+
}
23+
24+
let _: String = await Task.withUnsafeContinuation { continuation in
25+
continuation.resume(returning: "")
26+
}
27+
}
28+
29+
func test_unsafeThrowingContinuations() async {
30+
let _: String = try await Task.withUnsafeThrowingContinuation { continuation in
31+
continuation.resume(returning: "")
32+
}
33+
34+
let _: String = try await Task.withUnsafeThrowingContinuation { continuation in
35+
continuation.resume(throwing: MyError())
36+
}
37+
38+
// TODO: Potentially could offer some warnings if we know that a continuation was resumed or escaped at all in a closure?
39+
}

0 commit comments

Comments
 (0)