meisel meisel - 2 years ago 113
Objective-C Question

Atomic property of a nonatomic primitive vs. nonatomic property of an atomic primitive?

One issue that I have have with a property like:

@property (atomic, assign) NSInteger variable;

Is that if I forget it's atomic, I may reference the ivar directly and undo that atomicity. However, if I declare this:

@property (nonatomic, assign) _Atomic(NSInteger) variable;

Then it's always atomic whether I'm using the getter/setter or accessing the ivar, correct? So should we prefer the latter? My single-threaded benchmarks indicate that these two have similar speed for the setter, although I don't know if that changes depending on what's going on concurrently.

Answer Source

I'm not sure there is a definitive answer to your question, but as no other answers exist at the time of writing I'll offer the following in the hope it helps.

Declared properties, along with the nonatomic qualifier (by default properties were atomic and atomic did not exist), were introduced in Objective-C 2.0 circa 2009. _Atomic() comes from C11, circa 2011.

So we have two independent language developments addressing atomicity.

Objective-C is not rigorously defined, the last "specification" of the whole languages dates from 2009 despite extensions since then, and I know of no specification that discusses how the atomic features of C and the atomic properties of Objective-C interact. So as with many Objective-C questions it is down to what the compilers do.

With the current Xcode 8.x compilers targeting Intel appear to produce code which respects atomicity, up to at least 128 bits (the limits of testing for this answer), for all combinations of atomic and _Atomic() – though specifying both is somewhat redundant. Code produced for atomic is more likely to involve spin locks and of course involve function calls; while _Atomic() is more likely to use cpu exchange instructions and be compiled inline.

So should we prefer the latter? [_Atomic()]

If you intend to use direct access to the backing variable, and I'll skip any discussion of the merits or otherwise of doing that, then probably.

If you don't intend to access the backing variable directly then using Atomic() might exchange a spin lock call for a single cpu instruction, each with its own impacts, so any preference is down to how you weigh those.

In short: YMMV, the above applies to Intel, Xcode 8.x, etc. Hope it was some help, interesting question.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download