[Pitch #2] Actors

Yes, I'm intentionally leaving this as "functions" until we get more direction on the effect-ful properties bit. The += here is treating otherActor.state as inout, so I think it should be banned by the wording in this proposal that prevents inout with asynchronous calls.

It's most everything a class can do. The core data ones won't work because they depend on inheriting from NSManagedObject (which actors can't do). Anyway, I can document this. It was way easier when we had actor class ;)

@concurrent closures must be actor-isolated lest we create races. Non-@concurrent closures might or might not be actor-isolated. You surely want the ones passed to Sequence.map to be actor-isolated so you can access your own state within a sequential algorithm. (You note this with your forEach example as well)

Sure, but relying entirely on @concurrent leaves significant holes in the model if you try to tie it exactly to actor-independent. Existing APIs that take escaping closures and run them concurrently abound in Swift:

func runLater(_: @escaping (Int) -> Void) { ... }

actor MyActor {
  var numbers: [Int] = []

  func f() {
    runLater { // non-concurrent, therefore actor-isolated in your proposal
      numbers.append($0) // race condition
    }
  }
}

This is why @ktoso and I keep bringing up the "escaping implies not actor-isolated" approach in different forms. Perhaps we can tackle it directly by saying that escaping closure is always actor-independent.

It's frustrating to repeat my point and have it come back unrecognizably altered. It's not conflating the two, it is noting that we'd be leaving a large gap in the new model if one can escape an actor-isolated closure (where it will certainly be run concurrently) due to the lack of a @concurrent annotation in existing code. We've repeatedly noted that parallelForEach is an example of "non-escaping, concurrent", and the discussion is about spelling this rarer case as @nonconcurrent so that the defaults are right.

Actor-independent declarations are concurrent with respect to actor state, yes.

Sure.

I see how you can interpret that as giving people false hope. I realize now that we don't make the reference-cycle analogy in the document, but we should. It's a similar issue.

Huh, that's interesting. We might end up with a significant numbers of folks considering that to be an untenable middle ground, where the actors proposal is "unacceptable" without the ability to disable reentrancy. I do agree that we're in a better place now that we have an actual definition of what this attribute would look like, although I'd also love to have a prototype in place as well.

I'm not sure what you're referring to with "member lookup." AnyObject lookup occurs on values of type AnyObject, not on the self of a class type. We should probably ban references to synchronous @objc functions on an actor, whether via AnyObject lookup, #selector, or #keyPath, but otherwise I don't see a benefit to removing the ability to inherit NSObject. At the very least, we would want to be able to have actors provide NSObjectProtocol conformance (which we currently get through NSObject conformance) so that one can have an actor conform to various delegate protocols---which often have requirements that will come in as async or can be handled by performing the effects within a detached task.

I agree that this should be nailed down further. I'd rather keep it in the proposal (perhaps in its own section on ObjC interoperability later), because I think it's short and I'm running out of juggling hands.

Yes, I'm awaiting convergence.

Doug

5 Likes