Hi everyone. Thanks to everyone who participated in the review for SE-0392, Custom Actor Executors. The Language Workgroup accepts the proposal in principle, but has decided to return the proposal for revision. There are some relatively minor changes to the proposed API that we would like to see explored in a second round of review:
The proposal offers a function
assertOnActorExecutor(_: Actor)to assert that code is currently executing on the executor for a given actor instance, and some reviewers found the name confusing as to whether the actor instance itself or its sharedUnownedExecutor reference ought to be passed. The Language Workgroup wants to suggest turning this standalone function into a method, if possible. Variants of the method could be provided including an instance method for instantiated actors, a static method for global actors, and an instance method for serial executors, allowing for code to read naturally in any of the three cases.
There was concern about the use of the common term
Jobas a standard library type, both because it's likely to be frequently shadowed by
Jobdeclarations in other modules, and because
Jobhas similar connotations to
Task, and the presence of
Tasktypes together would be likely to confuse some developers. The Language Workgroup expects that code working with custom executors and jobs will be far less common than code that works with tasks, so giving the type a more unique and descriptive name like
ExecutorJobwould be appropriate. (If it were possible, the qualified name
Executor.Jobwould be nice, but since
Executoris a protocol, that would mean that every implementation of
Executorwould end up with a
Jobtype nested inside it.)
The proposal defines
Jobas a noncopyable type, which the Language Workgroup agrees is a great use of the new language feature, and the right thing to do. However, we expect that developers are likely to run into limitations given the initial subset of noncopyable type support provided by SE-0390. The proposal states that APIs using the
UnownedJobtype, which does not statically enforce single ownership will be deprecated, but we expect that developers may need to use
UnownedJobin the short- to medium-term to express things that are difficult to achieve with a noncopyable
Job. We agree that use of
Jobshould be encouraged where possible, but that it should be clear that
UnownedJobremains available as an escape hatch while the capabilities of noncopyable types continue to develop.
There was good discussion of what should happen when code asks a distributed actor instance what its executor is. The question doesn't really make sense to ask of a remote actor instance, since the only code that locally executes on its behalf is the nonisolated remote call stub, and it doesn't make sense to try to enqueue additional local work on a remote actor's executor. One possibility would be to have the
unownedExecutorproperty of an actor be
Optional, and have distributed actor instances return
nil, but the Language Workgroup agrees with the proposal's choice not to take this route, since doing so would add friction to code that only works with local actors. Instead of returning a "default" executor, though, the language workgroup would like to see if it's possible to use an executor implementation that raises a
fatalErrorif any code tries to enqueue additional jobs on it. Although it may make sense to ask an arbitrary actor for its executor to log the value as a debugging aid, it is likely a programming mistake to attempt to use that executor reference to enqueue work, so it may be preferable to trap at the attempt rather than to fall back to some default executor, to avoid expectations that the work will actually occur exclusively with work being done on the remote actor instance.
Thank you again to everyone who helped participate in the review!