swiftobjective-cactorbridge

ivar of Swift Actor in objc code: atomic or nonatomic?


If I have a swift Actor...

@objc public actor SomeActor: NSObject, SomeProtocol { ... }

...and I want to use it as an ivar in objc code, does it need to be listed as atomic to retain it's thread safety, or is it more performant to call it nonatomic?

Also, do I need to be referencing it with a getter to preserve its thread safety, or can I call it directly?

#import <ThisProject/ThisProject-Swift.h>

@interface SomeClass () <SomeId>
@property (strong, atomic, readwrite) SomeActor *someActor;
@end

...

    [SomeOtherClass someMethod:someActor];

vs

@interface SomeClass () <SomeId>
@property (strong, nonatomic, readwrite) SomeActor *someActor;
@end
    
...

    [SomeOtherClass someMethod:_someActor];

Solution

  • While Alexander answered your question (and you should feel free to accept his answer; +1), I offer a few clarifying observations:

    1. What is the purpose of atomic?

      The atomic qualifier on the property just dictates how Objective-C synthesized accessors handle the pointer to the actor and has nothing to with the actor’s internal behaviors. As the documentation says, atomic “means that the synthesized accessors ensure that a value [the pointer in this case] is always fully retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.”

      The atomic keyword simply ensures that the synthesized accessor methods atomically fetch and store the pointer address, itself. It has no bearing on the internal thread-safety (or lack thereof) of the object to which it points.

    2. Should one use atomic or nonatomic?

      In practice, atomic often introduces (admittedly negligible) overhead with limited benefit. Like Alexander, I almost always use nonatomic. If the Objective-C code has thread-safety issues, one often needs a higher-level of synchronization, rendering the atomic nature to the pointer largely moot. It depends the Objective-C code (which is not really relevant to the immediate question).

      But, as Alexander pointed out, whether you mark the property as atomic or nonatomic is irrelevant to the fact that you are pointing to an actor or some other class.

    3. Should you use the property getter, self.someActor, or access the backing ivar, _someActor?

      You did not explicitly ask this question, but one of your examples, you refer to someActor (which I presume means you intended to use the getter, though given the absence of either self. or the leading underscore, it is not entirely clear) and in the other, _someActor (the property’s backing ivar).

      As Programming with Objective-C says, “… it’s best practice for an object to access its own properties using accessor methods or dot syntax.” The two common exceptions to this rule are (a) in init; and (b) in manually implemented getters/setters, if any.

      So, in short, I would generally use self.someActor and not _someActor.

      Please note, I belabor this accessor vs. ivar distinction because the atomic/nonatomic only dictates the nature of the synthesized accessor methods. It has no effect on direct interaction via the ivar. Thus, an atomic ivar is a bit of a non-sequitur, as directly interacting with the ivar bypasses the accessors and their synthesized behaviors (including atomic), too.

    Bottom line, feel free to use nonatomic. And if you are trying to ensure that the Objective-C code, itself, is thread-safe, we would need to see any relevant code, but, generally, merely making the property atomic would be insufficient. The fact that you are dealing with an actor has no meaningful impact on the choice of atomic or nonatomic.


    For folks looking for a description of actor interoperability with Objective-C, see SE-0297 – Concurrency Interoperability with Objective-C.