Rule of thumb for #property atomicity? - objective-c

Is there a good rule of thumb for when nonatomic properties should be used in Objective-C (on the desktop or on the iPhone platform), as opposed to the default atomic properties? I understand the difference – atomicity guarantees an entire value at the expense of performance – but most examples I see use nonatomic properties (and aren't unstable), so there are evidently circumstances in which atomicity is required and circumstances under which it is not.
Can anyone provide me with a simple guideline for when I should use atomic properties and when I should favour nonatomic ones?

You should favor nonatomic whenever possible. In general, this means properties that will only be set/accessed from a single thread or properties whose access is protected by higher-level synchronization of some kind. It's important to note that atomic property access does not guarantee thread safety. In other words the algorithms that depend on the values of atomic properties must themselves be thread safe for the entire system to be thread safe. With this in mind, it is often possible to make the properties nonatomic while maintaining the thread safety of the system.

Related

Does atomic actually mean anything for a synthesized primitive?

In Android, I could safely access and modify primitive types from different threads. I used this to share data between my OpenGL draw loop and user settings that were modified in the main thread Android UI. By storing each setting in a primitive type and making each independent of the others' values, it was thread-safe to modify all these variables without using locks or the synchronize keyword.
Is this also true in Objective-C? I read that placing atomic on a variable essentially causes the synthesized getter and setter to use locks, similar to using synchronized methods in Java. And I've read that the reason for this is so an object does not get partially modified while it's being read by another thread.
But are primitive types safe from being partially modified, as they are in Java? If that is the case, it seems like I could use my same old paradigm from Java for sharing data between threads. But then the atomic keyword would be pointless for a primitive, correct?
I also read that a more robust and faster solution than using atomic variables is to copy objects before using them if they are accessed from multiple threads. But I'm not sure how that could be accomplished. Couldn't a nonatomic object get modified while it's in the process of being copied, thereby corrupting the copy?
Primitive types aren't guaranteed to be safe from being partially modified because modifications to primitive types aren't guaranteed to be atomic in C and Objective-C inherits from there. C's only guarantees concern sequence points and there's no requirement that the processing between two sequence points be atomic — a rule of thumb is that each full expression is a sequence point.
In practice, modifying primitives is often a two-step process; the modification is made in a register and then written out to memory. It's very unlikely that the write itself will not be atomic but there's also no guarantee of when it will occur versus the modification. Even with the volatile qualification, the only guarantees provided are in terms of sequence points.
Apple exposes some C functions for atomic actions via OSAtomic.h that map directly to the specialised atomic instructions that CPUs offer for the implementation of concurrency mechanisms. It's possible you could use one of those more directly than via a heavy-handed mutex.
Common patterns in Objective-C are:
immutable objects and functional transformations — there are memory management reasons as well but that's partly why NSString, NSArray, etc, are specifically distinct from NSMutableString, NSMutableArray, etc;
serial dispatch queues, which can be combined with copy-modify-replace by copying on the queue, going off somewhere else to modify, then jumping back onto the queue to replace;
such #synchronizeds, NSConditionLocks or other explicit synchronisation mechanisms as are appropriate.
The main thread itself is a serial dispatch queue, which is why you can ignore the issue of concurrency entirely if you restrict yourself to it.
Atomic synthesized #properties are immune to concurrent partial updates. The accessor methods will use a lock if necessary on that architecture.
In general, primitive types in C are not necessarily safe with respect to concurrent partial updates.
I don't believe you can partially modify a primitive type, that's part of what makes them primitive. You either modify it or you don't. In that sense, I would say that they are thread safe.
You are correct when you say that the atomic keyword would be pointless for a primitive type.
Someone already took a stab at this here:
Objective-c properties for primitive types

Why are Cocoa's IBOutlet properties atomic by default, and Cocoa Touch's aren't?

If you drag a new outlet from Interface Builder to an interface (header) file, Xcode 4.6 will automatically create a property for you...
On iOS (Cocoa Touch) it will look like this:
#property (weak, nonatomic) SomeClass *someProperty; //nonatomic accessors
Whereas on OS X (Cocoa) it will look like this:
#property (weak) SomeClass *someProperty; //atomic accessors (implicitly)
Why?
EDIT: I am not asking about what atomic does or doesn't do, I'm well aware of the synchronize directive and the underlying mutex (or lock or whatever) that guarantees atomicity of the setter and getter. I know that on iOS, accessors are nonatomic because UIKit is not thread safe, and so there is nothing to be gained by making them atomic, it's just a waste of processor time and battery life. I am talking about the default case here, programmers who know what they are doing will know when they need to make their accessors atomic.
So I'm asking why they are atomic by default on OS X. I was under the impression that Appkit was not thread safe either. And having atomic accessors doesn't guarantee thread safety, I'd even go as far as to say it goes the opposite way in that it can give the illusion of thread safety to novice programmers and make bug tracking harder in concurrent apps by deferring crashes to a later time and in so doing making them harder to trace. And just because desktop computers are relatively powerful doesn't mean resources should be wasted (note I am not talking about premature optimization here), and since it stands to reason that Apple engineers are reasonable programmers, there must be a good reason why they have decided to make the properties synthesize atomic accessors by default.
In this context the atomic specifier tells the compiler that the setter and accessor should be synthesised so as to be safe to call from multiple threads. This adds a small overhead by requiring the methods to take out a lock before a properties value can be written or read.
Since user interface elements of both UIKit and Cocoa are only ever intended to be accessed from the main thread the extra lock is unnecessary. The overhead of making a property atomic is pretty minimal, but in the more constrained environment of iOS every little ounce of speed is valuable.. hence why iOS defaults to using nonatomic properties for IB Outlets.
Edited in response to your expanded question: My feeling is that the cost of using atomic properties is worth the overhead on the Mac. Theres an argument that using atomic properties masks a collection of bugs and is therefore a bad thing. I'd argue that from a users perspective Apple should set the defaults so that even badly coded applications crash less. It puts the onus on advanced programers to know when it's safe to use nonatomic properties in exchange for a performance advantage.
Without hearing from someone on the team at the time we can only speculate about their thought process but I'm sure it was a considered decission.
Simple as hell: atomic causes overhead (negligible one on OSX) with its implicit mutex mechanisms.
iOS (as an embedded system on a ARM chip) can't afford this overhead, hence IBOutlets defaulting to nonatomic.
In one word: Performance.
As to why they default to atomic on OSX, thread-safety on properties is a nice thing to have in a massively multi-threaded, multi-application environment like OSX (especially compared to iOS, apps are more likely to interact with each other on OSX than on iOS).
And as said before, the overhead is really negligible on OSX, thus they defaulted it like this.
There was a rather lengthy debate about atomic vs. non-atomic properties in this question: What's the difference between the atomic and nonatomic attributes? and I would wager that it has more to do with the relative complexity of the interfaces generally found in OSX apps vs. iOS apps. It is fairly common to have an OSX app running on multiple threads all the time. The interfaces thus lend themselves to operating more commonly in a multi-threaded environment. In iOS, while apps are certainly gaining complexity as the system matures, they are still running on a much more basic OS that currently lends itself favorably to a non-threaded environment.
There is also some talk about non-atomic properties generally having less overhead vs. atomic ones and with smaller CPUs and less memory generally found in iOS devices, it would make sense to default properties to nonatomic unless the extra overhead is warranted.
OSX can control multiple threads, and most of the application uses multiple threads. Therefore the default is set to atomic.
While in case of iOS, rarely you go for multiple threads so non-atomic serves you.

nonatomic in multi threaded iOS environment

Most iPhone code examples use the nonatmoc attribute in their properties. Even those that involve [NSThread detachNewThreadSelector:....]. However, is this really an issue if you are not accessing those properties on the separate thread?
If that is the case, how can you be sure nonatomic properties won't be accessed on this different in the future, at which point you may forget those properties are set as nonatomic. This can create difficult bugs.
Besides setting all properties to atomic, which can be impractical in a large app and may introduce new bugs, what is the best approach in this case?
Please note these these questions are specifically for iOS and not Mac in general.
First,know that atomicity by itself does not insure thread safety for your class, it simply generates accessors that will set and get your properties in a thread safe way. This is a subtle distinction. To create thread safe code, you will very likely need to do much more than simply use atomic accessors.
Second, another key point to know is that your accessors can be called from background or foreground threads safely regardless of atomicity. The key here is that they must never be called from two threads simultaneously. Nor can you call the setter from one thread while simultaneously calling the getter from another, etc. How you prevent that simultaneous access depends on what tools you use.
That said, to answer your question, you can't know for sure that your accessors won't be accessed on another thread in the future. This is why thread safety is hard, and a lot of code isn't thread safe. In general, if youre making a framework or library, yeah, you can try to make your code thread safe for the purposes of "defensive programming", or you can leave it non-thread safe. The atomicity of your properties is only a small part of that. Whichever you choose, though, be sure to document it so users of your library don't have to wonder.

Why is "atomic" a default #property qualifier in Objective C when I find myself using nonatomic 100% of the time?

In my few years as an iOS developer I don't think I've ever used atomic on a property. If I can see potential race conditions or data integrity issues due to threading, using atomic on a #property wouldn't ever help. I use conventional transaction/unit-of-work thread safety techniques (using mechanisms locks, semaphores or whatever).
Does anyone have (or know of) any practical examples of where atomic is used? (I'd love to see some actual/practical code examples)
After writing nonatomic for maybe the billionth time, I'm also wondering why Apple have decided to make atomic the default.
As for the first problem you're having, maybe it's because
Although “atomic” means that access to the property is thread-safe, simply making all the properties in your class atomic does not mean that your class or more generally your object graph is “thread safe”—thread safety cannot be expressed at the level of individual accessor methods.
As for why apple makes it atomic by default, I don't think there is any good reason, it was simply a bad design decision. Guys at the WWDC sessions repeatedly encouraged people to use nonatomic wherever you can to eliminate the performance impact.
It's worth noting that under garbage collection, almost all synthesized accessors are inherently atomic—there would be no difference between the atomic and nonatomic version, since the simple assignment of a pointer is all that's required in both cases. Since you really can't make a nonatomic synthesized accessor under garbage collection, they may have decided that it made more sense to just have things atomic by default.
I don't have any evidence that this was the reasoning behind the decision, but it makes sense to me.
(In case you're curious, there are still cases under garbage collection where simple assignment is nonatomic—this happens when the value is larger than the word size of the process. In practice, that only happens with structs.)
Edit: Added sources
More information on the atomicity of synthesized properties under garbage collection can be found in The Objective-C Programming Language -> Declared Properties -> Performance and Threading, where it says "In a garbage collected environment, most synthesized methods are atomic without incurring this overhead." The inherent atomicity is mentioned more explicitly in the 2008 WWDC session 420 "Using Garbage Collection with Objective-C", around the 29 minute mark.
In two words - thread safety. Most of the applications we write on a regular basis are fairly simple and as such are actually going to benefit from not having the additional locks.
From Apple's The Objective-C Programming Language:
Properties are atomic by default so that synthesized accessors provide robust access to properties in a multi-threaded environment—that is, the value returned from the getter or set via the setter is always fully retrieved or set regardless of what other threads are executing concurrently. For more details, see “Performance and Threading.”
If you do not specify nonatomic, then in a reference counted environment a synthesized get accessor for an object property uses a lock and retains and autoreleases the returned value—the implementation will be similar to the following:
[_internal lock]; // lock using an object-level lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
If you specify nonatomic, then a synthesized accessor for an object property simply returns the value directly.
When Apple first introduced the concept of properties, there was a big argument about whether atomic or nonatomic should be the default and the atomic people won.
I think the reasoning is that in a threaded environment, unless the property is atomic, you can't guarantee that the pointer it returns is valid. A non atomic getter would be implemented something like this
-(MyObj*) someProperty
{
return someInstVar;
}
It's possible that some other thread could deallocate the object pointed to by someInstVar after the pointer has been placed in the register for returning but before the caller has had time to retain it. Even this is no good:
-(MyObj*) someProperty
{
return [[someInstVar retain] autorelease];
}
because some other thread could dealloc someInstVar just before the retain count is incremented.
The only way to safely return the pointer in a multithreaded environment is something like this:
-(MyObj*) someProperty
{
#synchronized(self)
{
return [[someInstVar retain] autorelease];
}
}
and also to synchronise the setter too.
However, the problem with that is that the lock is very expensive (in reality they used something much lighter than #synchronized but it's still expensive) so everybody was using nonatomic anyway and just making all the properties atomic doesn't confer thread safety in general so other techniques are required anyway and they tend to obviate the problem I discussed above.
There are plenty of people who think the wrong decision was made about what the default should be, but it can't be changed now for backwards compatibility. I find myself typing nonatomic without even thinking now.
Atomic calls are calls that cannot be interrupted. The entire call must be executed.
Updating something like a shared counter variable would be something that could be atomic because you wouldn't want two processes trying to access the variable at the same time. The actions would need to be executed "atomically".
There is a lot of useful information in this SO post: Atomic vs nonatomic properties as to what the differences are and the thread safety issues of atomic vs nonatomic.

Locking details of synthesized atomic #properties in Obj-C 2.0

The documentation for properties in Obj-C 2.0 say that atomic properties use a lock internally, but it doesn't document the specifics of the lock. Does anybody know if this is a per-property lock, a per-object lock separate from the implicit one used by #synchronized(self), or the equivalent of #synchronized(self)?
Looking at the generated code (iOS SDK GCC 4.0/4.2 for ARM),
32-bit assign properties (including struct {int32_t v;}) are accessed directly.
Larger-than-32-bit structs are accessed with objc_copyStruct().
double and int64_t are accessed with objc_copyStruct, except on GCC 4.0 where they're accessed directly with stmia/ldmia (I'm not sure if this is guaranteed to be atomic in case of interrupts).
retain/copy accessors call objc_getProperty and objc_setProperty.
Cocoa with Love: Memory and thread-safe custom property methods gives some details on how they're implemented in runtime version objc4-371.2; obviously the precise implementation can vary between runtimes (for example, on some platforms you can use atomic swap/CAS to spin on the ivar itself instead of using another lock).
The lock used by atomic #properties is an implementation detail--for appropriate types on appropriate platforms, atomic operations without a lock are possible and I'd be surprised if Apple was not taking advantage of them. There is no public access to the lock in any case, so you can't #synchronize on the same lock. Several Apple engineers have pointed out that atomic properties do not guarantee thread safety; atomic properties only guarantee that gets/sets of that value are atomic. For correct thread safety, you will have to make use of higher-level locking or synchronization and you almost certainly would not want to use the same lock as the synthesize getter/setter(s) might be using.