SE-0306: Actors

Two random points of order:

  1. Please maintain professional and civil tone of discussion on the Swift forums. Some of the comments above are getting borderline. We are all friends here, and want the best for the Swift language even if we disagree about the details of that.

  2. This is an official proposal review thread, and the intent of the swift evolution process is that people should not have to read all the pitch threads, patches and comments. That means that it is good for this thread to be self contained.

If you have a position that isn't represented here, then I encourage you to explain it, even if it was discussed in another place. It is helpful to explain the "why" of your position (i.e. the principles that guide your position), not just the "what" that you want to see.

-Chris

36 Likes

The problem with AnyActor is that while we have the term Object to refer to a Class instance, we don't have such simple words to refer to enum/closure/struct/actor instances.

3 Likes

Why would you use a class if could use an actor that can do everything a class can (in addition to static concurrency guaranties)?

1 Like

If an "actor" is just a class with an actor-context applied (like "@tempPrivateActor class XYZ", where tempPrivateActor is a global actor only used for XYZ), then that sort of solves the "should actors support inheritance" question, I guess? [Pitch] Global actors - #9 by JJJ

1 Like

You are committing a Begging the Question fallacy with your reasoning. You are first assuming actors are classes to support the idea that they are classes. The fact that actors could be thought of "monogamous" (I think this analogy holds better than using the word "private") global actors applied to classes doesn't hold because you could apply the same reasoning to structs. As far as I understand, you can apply global actors to any type, including structs/enums. So from what I understood from your reasoning, actors could be just as well structs/enums hiding behind sugar to "monogamous" global actors applied only to that given struct or enum. I hope you don't mind me pointing the issues with your reasoning so bluntly. I don't want to sound rude in any way. English is not my first language and besides language there are always cultural differences as well.

1 Like

I disagree. I see it exactly the other way around: Global actors are a retrofit to make classes work with the new actor model. And since classes are the legacy requirement, there is no need for actors to add legacy features.

1 Like

It didn't sound rude at all, and I fully agree :slight_smile: :+1: That's why I started with "If an actor is".

But still, as I see it an actor could easily be implemented as a class with a global actor applied. Structs for example would not cut it (as they are not reference types).

I also agree that it would be nice to use the opportunity to start fresh with actors, and not repeat any mistakes made with the design of classes. If I was implementing this, though, it would be super tempting to just make them classes with actor contexts, though :slight_smile: Everything is already defined and specified because they are just classes, and it needs to be implemented anyway because of global actors.

1 Like

Yeah, I loved the global actors proposal. In fact, I see it as the nail in the coffin of the argument of compatibility with existing codebase that use classes. Also, I actually see @JJJ's argument in complete opposite light. Given that one can add isolation to existing classes with global actors, effectively turning classes into actors, then there's no reason at all, IMO, to bring inheritance to actors. If you really really want inheritance and isolation, use classes and global actors. I now definitely don't see any reason to bring inheritance to actors.

Classes are not a subset of actors. You can change the state of a class object from multiple threads - you can not do that with an actor. That is the benefit you get from actors - and it is the reason why you can not simply change your classes to actors.

Holy cow, you are right! Totally missed that.

This is incorrect. See the other thread.

I agree it goes both ways :+1:

I guess what I'm asking, really, is whether the Swift community wants to add this extra complexity to the language (both specification, implementation, and learning), or perhaps just want to piggyback on the existing "class" type.

1 Like

Apparently, what I said is not true according to @xwu in the other thread.

@xwu this reasoning would be incorrect, then?

Yeah, I was wrong. As soon as you have more than one instance, this doesn't hold. You would not be able to create a hierarchy of actors where two such "actors" would be truly isolated by each instance having its own execution context. I'm not sure that matters, though. But they would not be real actors.

Hmm. Are there any negative consequences of making actors share the same execution context? If a runtime is allowed to run this on a machine without any threading, then everything would basically just run on the MainActor, right? Is that allowed?

So actors would not be able to execute work in parallel, of course. But apart from that?

Is the Swift Concurrency Runtime allowed to merge execution contexts at will? Are there any rules for when that is OK?

Personally, I'd remove actor and simply replace it with isolated class. We can then rethink of everything in term of isolation alone:

// the class has its own isolation context (it's an actor)
isolated class MyActor {
   func isolatedMember() { ... }
   nonisolated func nonisolatedMember() { ... }
}
// the class is attached to a global actor isolation context
isolated(MainActor) class MyObject {
   func isolatedMember() { ... }
   nonisolated func nonisolatedMember() { ... }
}
// the class has no isolation context, but one of its member is isolated to the main actor
class MyObject {
   func nonisolatedMember() { ... }
   isolated(MainActor) func isolatedMember() { ... }
}

I know nonisolated and global actors where split from this proposal in order to make it simpler, but I'm not sure those splits were warranted. It seems to me we might be slicing things into too many concepts for no good reason, and that it ultimately makes things complicated.

5 Likes

This is not a bad idea actually!

For one thing, that solves the inconsistency where "an instance of a class is an object" but "an instance of an actor is an actor".

Could one have an "isolated struct" or an "isolated enum"? What would that mean? As far as I understand we can apply global actors to structs and enums, could one "isolate" any type?

1 Like