Commit Graph

259 Commits

Author SHA1 Message Date
John McCall
2012195cd5 Alter the runtime interface for awaiting futures and task groups.
First, just call an async -> T function instead of forcing the caller
to piece together which case we're in and perform its own copy.  This
ensures that the task is actually kept alive properly.

Second, now that we no longer implicitly depend on the waiting tasks
being run synchronously, go ahead and schedule them to run on the
global executor.

This solves some problems which were blocking the work on TLS-ifying
the task/executor state.
2021-02-21 23:48:13 -05:00
Konrad `ktoso` Malawski
a226259d84 [Concurrency] TaskGroup moves out of AsyncTask, non escaping body 2021-02-22 13:26:27 +09:00
Konrad `ktoso` Malawski
40b6b18945 [Concurrency] implement withCancellationHandler via records 2021-02-18 17:27:15 +09:00
swift-ci
c19375790a Merge pull request #35977 from DougGregor/discardable-run-detached 2021-02-15 14:51:51 -08:00
Doug Gregor
6a5dfb8aa4 Mark Task.runDetached as @discardableResult.
Often, this API is used for its side effects and nobody cares about the
handle.
2021-02-15 12:21:49 -08:00
Konrad `ktoso` Malawski
d2bd6abe61 [Concurrency] TaskLocals allow configuring inheritance: never 2021-02-13 20:09:11 +09:00
Konrad `ktoso` Malawski
b811b12246 [Concurrency] TaskLocals lookup "skip" optimization 2021-02-13 10:39:22 +09:00
Konrad `ktoso` Malawski
1044723787 [Concurrency] Initial Task Local Values implementation 2021-02-13 10:39:22 +09:00
Evan
e813bbea76 Merge pull request #35911 from etcwilde/ewilde/deprecate-runAsyncAndBlock
Deprecate runAsyncAndBlock API
2021-02-12 09:51:04 -08:00
Konrad `ktoso` Malawski
a55ebff942 [Concurrency] deprecate not implemented Task functions, until they're implemented 2021-02-12 16:33:16 +09:00
Konrad `ktoso` Malawski
e7cfc8c018 [Concurency] Improve priority testing, including multi-task escalation 2021-02-12 09:06:17 +09:00
Konrad `ktoso` Malawski
08de933288 [Concurrency] Task revisions 3
- introduce UnsafeCurrentTask
- implement Hashable, Equatable on tasks
- assume we'll have a way to get a task from sync context
- Task.Handle now has a Failure type as well
- Task.Handle.getResult
2021-02-12 09:06:17 +09:00
Evan Wilde
e83b0a2a84 Deprecate runAsyncAndBlock API
We don't want people using this as a means of jumping from synchronous
code to async code. It blocks the thread that it's running on and spawns
a new thread to run the async code.

This has a couple of drawbacks. First, if it blocks a thread that is
needed by the async code (i.e, calling something on the main actor while
blocking the main thread), it is an immediate deadlock. This is a bad
day for everyone. Second, it can easily lead to thread-explosions.

The proper entry-point for async code is to use something of the
following form:

```
@main
struct Main {
  static func main() async {
    // ...
  }
}
```

This should take care of most new code. There are still places where
folks will need to jump from synchronous code to async code. That still
needs to be designed and implemented, but we don't want people to come
to rely on `runAsyncAndBlock`.
2021-02-10 21:33:03 -08:00
Doug Gregor
1f1f703afe Drop @concurrent from parameter to @asyncHandler entry point.
The async handler code doesn't really run concurrently with where it is
launched, despite the implementation currently using `runDetached`
internally. Drop the @concurrent and bitcase it back on when needed.
2021-01-29 09:53:22 -08:00
Doug Gregor
9efb44fde8 Adopt @concurrent in Task APIs 2021-01-28 10:03:09 -08:00
Konrad `ktoso` Malawski
80ee936a72 Revert "[Concurrency] isCanceled spelling to follow guidance" 2021-01-23 07:27:34 +09:00
Konrad `ktoso` Malawski
8b37455774 [Concurrency] isCanceled spelling to follow guidance 2021-01-22 12:09:19 +09:00
Evan Wilde
81ae9d663f More tests and cleanup
Adding execution and death test to ensure that we crash appropriately
when the main function throws an uncaught exception, and that the async
main runs correctly.

Also switching to doing the CFRunLoopRun lookup with `RTLD_DEFAULT`
since `RTLD_SELF` isn't available on Linux.

Switching to `try await` since `await try` is no longer the right way to
do that.

Using exit(0) instead of EXIT_SUCCESS since the C++ importer doesn't
mark imported macros with @actorIndependent yet.
2021-01-14 13:28:58 -08:00
Evan Wilde
6b16657922 Explode on uncaught error thrown in main
This patch has two desirable effects for the price of one.
 1. An uncaught error thrown from main will now explode
 2. Move us off of using runAsyncAndBlock

The issue with runAsyncAndBlock is that it blocks the main thread
outright. UI and the main actor need to run on the main thread or bad
things happen, so blocking the main thread results in a bad day for
them.

Instead, we're using CFRunLoopRun to run the core-foundation run loop on
the main thread, or, dispatch_main if CFRunLoopRun isn't available.
The issue with just using dispatch_main is that it doesn't actually
guarantee that it will run the tasks on the main thread either, just
that it clears the main queue. We don't want to require everything that
uses concurrency to have to include CoreFoundation either, but dispatch
is already required, which supplies dispatch_main, which just empties
out the main queue.
2021-01-13 15:49:28 -08:00
Evan Wilde
c01b9f000e Adding async-main support
This patch adds the async-main start-point for programs.
When a `static func main() async` is inserted into the main program, it
gets called through `_runAsyncMain` instead of calling directly. This
starts the program in an async context, which is good because then we
can do async stuff from there.

The following code

```
@main struct MyProgram {
  static func main() async {
    // async code
  }
}
```

is turned into

```
@main struct MyProgram {
  static func $main() {
    _runAsyncMain(main)
  }

  static func main() async {
    // async code
  }
}
```

_runAsyncMain code-gen's to the same thing as runAsyncAndBlock, which
emits a call to `swift_task_runAndBlockThread`.
2021-01-13 13:17:35 -08:00
Doug Gregor
3c38ffe0ea [Concurrency] await try -> try await
The `try await` ordering is both easier to read and indicates the order
of operations better, because the suspension point occurs first and
then one can observe a thrown error.
2020-12-23 13:21:59 -08:00
Erik Eckstein
29543d4997 Revert "[Concurrency] Workaround for _runAsyncHandler."
This reverts commit 5cac8d0152.
2020-12-17 16:33:03 +01:00
swift-ci
81ef1bd36f Merge pull request #35135 from DougGregor/concurrency-runasynchandler-workaround 2020-12-16 21:54:21 -08:00
Doug Gregor
5cac8d0152 [Concurrency] Workaround for _runAsyncHandler.
Work around an expected miscompile in _runAsyncHandler.
2020-12-16 19:37:50 -08:00
Konrad `ktoso` Malawski
b267778bf1 Rebased to use new global executor 2020-12-17 06:05:13 +09:00
Konrad `ktoso` Malawski
9e1ecc539c [Concurrency] guard offer/poll with a lock for now; cleanups 2020-12-17 06:05:13 +09:00
Konrad `ktoso` Malawski
7b37554096 [Concurrency] Initial TaskGroup implementation working 2020-12-17 06:05:13 +09:00
Konrad `ktoso` Malawski
520b513e8a [Concurrency] Task: isCancelled,checkCancelled implementation
move comments to the wired up continuations

remove duplicated continuations; leep the wired up ones

before moving to C++ for queue impl

trying to next wait via channel_poll

submitting works; need to impl next()
2020-12-17 06:05:13 +09:00
Doug Gregor
35acd40b1e +concurrency task groups initial work in progress 2020-12-17 06:05:13 +09:00
Doug Gregor
d6060153d2 Merge pull request #35059 from jckarter/integrate-objc-interop-with-task-runtime
Integrate ObjC interop intrinsics with task runtime.
2020-12-12 18:10:35 -08:00
Doug Gregor
7a7179d983 Merge pull request #35071 from DougGregor/with-one-unsafe-continuation
[Concurrency] Remove extraneous copies of withUnsafe(Throwing)Continuation
2020-12-11 20:59:38 -08:00
Doug Gregor
1a15eb1b7c [Concurrency] Remove extraneous copies of withUnsafe(Throwing)Continuation 2020-12-11 15:42:35 -08:00
Joe Groff
2ee6b70402 Integrate ObjC interop intrinsics with task runtime. 2020-12-11 09:20:02 -08:00
Doug Gregor
79e66210a0 [Concurrency] Schedule "async let" child tasks.
This provides runtime support for "async let". Add a simple test of
"async let" along with a simple test of the actor runtime.
2020-12-10 23:53:10 -08:00
John McCall
1177cde4e3 Use current public Dispatch API to schedule global work.
We expect to iterate on this quite a bit, both publicly
and internally, but this is a fine starting-point.

I've renamed runAsync to runAsyncAndBlock to underline
very clearly what it does and why it's not long for this
world.  I've also had to give it a radically different
implementation in an effort to make it continue to work
given an actor implementation that is no longer just
running all work synchronously.

The major remaining bit of actor-scheduling work is to
make swift_task_enqueue actually do something sensible
based on the executor it's been given; currently it's
expecting a flag that IRGen simply doesn't know to set.
2020-12-10 19:18:53 -05:00
Joe Groff
5087e411c2 SILGen: Implement native-to-foreign thunks for async methods.
Bridging an async Swift method back to an ObjC completion-handler-based API requires
that the ObjC thunk spawn a task on which to execute the Swift async API and pass
its results back on to the completion handler.
2020-12-08 10:04:40 -08:00
Erik Eckstein
863dcec142 [concurrency] stdlib: add a _runAsyncHandler compiler intrinsic.
It just calls Task.runDetatched.
It's more efficient to have a non-generic compiler intrinsic than to let the compiler call the generic Task.runDetatched.
The _runAsyncHandler doesn't have to be generic because the return value of the run function is defined to be Void.
2020-12-01 08:42:56 +01:00
Joe Groff
822f8577e6 Merge pull request #34817 from jckarter/coalesce-unsafe-continuations
Coalesce multiple `Unsafe*Continuation` definitions.
2020-11-30 10:30:48 -08:00
Doug Gregor
dab6fb7098 [Concurrency] Implement SIL generation for "async let".
Implement SIL generation for "async let" constructs, which involves:

1. Creating a child task future at the point of declaration of the "async let",
which runs the initializer in an async closure.
2. Entering a cleanup to destroy the child task.
3. Entering a cleanup to cancel the child task.
4. Waiting for the child task when any of the variables is reference.
5. Decomposing the result of the child task to write the results into the
appropriate variables.

Implements rdar://71123479.
2020-11-27 22:50:39 -08:00
Konrad `ktoso` Malawski
fd8097c2d2 not owned 2020-11-20 00:46:40 -08:00
Konrad `ktoso` Malawski
7126f32f22 fix properly, by using Task.JobFlags which does conversions 2020-11-20 00:46:40 -08:00
Konrad `ktoso` Malawski
7615c707d6 [Concurrency] Fix priority implementation 2020-11-20 00:46:40 -08:00
Konrad `ktoso` Malawski
261f0d2dcd +task Implement Task.currentPriority 2020-11-20 09:00:41 +09:00
Joe Groff
f922eb237c Coalesce multiple Unsafe*Continuation definitions.
We somehow ended up with a set hidden in `Task` as well as a set at top level. SILGen currently
hooks into the top-level ones, so shed the `Task`-namespaced versions for now.
2020-11-19 09:05:11 -08:00
Doug Gregor
894528062d [Concurrency] Implement Task.Handle.get() in terms of an async runtime call.
Switch the contract between the runtime operation `swift_future_task_wait`
and Task.Handle.get() pver to an asynchronous call, so that the
compiler will set up the resumption frame for us. This allows us to
correctly wait on futures.

Update our "basic" future test to perform both normal returns and
throwing returns from a future, either having to wait on the queue or
coming by afterward.
2020-11-18 22:02:14 -08:00
Doug Gregor
a1284d062c [Concurrency] Stop runDetached from actually printing/running the task.
Rather than immediately running the task synchronously within
runDetached, return the handle to the newly-created task. Add a method
task.Handle.run() to execute the task. This is just a temporary hack
that should not persist in the API, but it lets us launch tasks on a
particular Dispatch queue:

```swift
extension DispatchQueue {
  func async<R>(execute: @escaping () async -> R) -> Task.Handle<R> {
    let handle = Task.runDetached(operation: execute)

    // Run the task
    _ = { self.async { handle.run() } }()

    return handle
  }
}
```

One can pass asynchronous work to DispatchQueue.async, which will
schedule that work on the dispatch queue and return a handle. Another
asynchronous task can then read the result.

Yay for rdar://71125519.
2020-11-17 10:04:26 -08:00
Doug Gregor
2a41920c00 [Concurrency] Implement basic runDetached on top of createAsyncTaskFuture. 2020-11-15 22:37:13 -08:00
Arnold Schwaighofer
193a3d5a8f Temporarily add runAsync to run a task synchronously in the current thread
Add a temporary runtime entry to run a task synchronous.
2020-11-13 10:41:42 -08:00
Doug Gregor
c291eb596b [Concurrency] Add cancelAsyncTask() builtin.
Implement a new builtin, `cancelAsyncTask()`, to cancel the given
asynchronous task. This lowers down to a call into the runtime
operation `swift_task_cancel()`.

Use this builtin to implement Task.Handle.cancel().
2020-11-05 13:50:17 -08:00
Konrad `ktoso` Malawski
27d734a709 [Concurrency] Include Task.sleep(until:) and Task.yield() placeholders 2020-11-02 20:51:00 +09:00