Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add discussion about distributed actors #1

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions proposals/nnnn-closure-isolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class NonSendableType {

## Proposed solution

### Explicit closure isolation

Enable explicit specification of non-isolation by allowing `nonisolated` to be a specifier on a closure:

```swift
Expand All @@ -82,6 +84,36 @@ actor A {
}
```

The same mechanism works with distributed actors, however only statically "known to be local" distributed actors may be promoted to `isolated`. Currently, this is achieved only through an `isolated` distributed actor type, meaning that a task can only be made isolated to a distributed actor if the value already was isolated, like this:

```
import Distributed

distributed actor D {
func isolateSelf() {
// 'self' is isolated
Task { [isolated self] in print("OK") } // OK: self was isolated
}

nonisolated func bad() {
// 'self' is not isolated
Task { [isolated self] in print("BAD") } // Error: self was not isolated, and may be remote
}
}

func isolate(d: isolated D) {
Task { [isolated d] in print("OK") } // OK: d was isolated, thus known-to-be-local
}

func isolate(d: D) {
Task { [isolated d] in print("OK") } // Error: d was not isolated, and may be remote
}
```

While it is technically possible to enqueue work on a remote distributed actor reference, the enqueue on such actor will always immediately crash. Because of that, we err on the side of not allowing such illegal code to begin with. Future directions discuss how this can be made more powerful when it is known that an actor is local. Worth reminding is also the `da.whenLocal { isolated da in ... }` API, which allows dynamically recovering an isolated distributed actor reference, after it has dynamically been checked for locality.

### Isolation inheritance

Provide a formal replacement of the experimental parameter attribute `@_inheritActorContext` to resolve its ambiguity with closure isolation. Its replacement `@inheritsIsolation` changes the behavior so that it unconditionally and implicitly captures the isolation context (as opposed to currently in actor-isolated contexts it being conditional on whether you capture an isolated parameter or isolated capture or actor-isolated function, but guaranteed if the context is isolated to a global actor or `nonisolated`).

```swift
Expand Down Expand Up @@ -187,6 +219,26 @@ Despite this being a useful pattern, it does not address the underlying inherita

There was also discussion about the ability to make synchronous methods on actors. The scope of such a change is much larger than what is covered here and would still not address the underlying differences.

## Future directions

### "Known to be local" distributed actors and isolation

Distributed actors have a property that is currently not exposed in the type-system that is "known to be local". If a distributed is known to be local, code may become isolated to it.

Once the locality of a type is expressed in the type system the following would be possible:

```
let worker: local Worker

// silly example, showcasing isolating on a known-to-be-local distributed actor
func work(item: Item) async {
await Task { [isolated worker] in
worker.work(on: item)
}.value
}
```

## Acknowledgments

Thank you to Franz Busch and Aron Lindberg for looking at the underlying problem so closely and suggesting alternatives. Thank you to Holly Borla for helping to clarify the current behavior, as well as suggesting a path forward that resulted in a much simpler and less-invasive change.