Sometimes we have a simple readOnly Property whose value may change
@property (readonly) NSFetchedResultsController * FetchController;
@property (readonly) NSFet
It is a common misconception to consider read-only operations as atomic in nature. It isn't guaranteed. It is also a common misconception that atomicity guarantees thread safety, but that is a different subject.
The difference between atomic and nonatomic on readonly properties is that atomic
(which is the default, but not declared) guarantees that the value returned from the readonly retrieval method is integral.
That is, if it is an object, it will be retained and autoreleased. If it is a struct, an appropriate lock will have been used to ensure an integral value of the struct was returned.
Note that simply because a property is declared publicly readonly does not preclude it being re-declared as readwrite for internal use. Thus, the difference between atomic and nonatomic might be quite significant; a class might declare a readonly property as nonatomic while also documenting that all API on the class must be used from one thread only.
I think you're misunderstanding what atomic
(or more appropriately, nonatomic
) means in this context. The simplest explanation can be found in objc-accessors.mm itself:
id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
// Retain release world
id *slot = (id*) ((char*)self + offset);
if (!atomic) return *slot;
// Atomic retain release world
spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
_spin_lock(slotlock);
id value = objc_retain(*slot);
_spin_unlock(slotlock);
// for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
return objc_autoreleaseReturnValue(value);
}
As you can see, atomicity here refers only to the validity of the returned object. It it retained and autoreleased in order to guarantee that it does not get deallocated while you are using it.
If this [[obj retain] autorelease]
was not performed, another thread could set the property, which would cause the previous property (i.e. the one you're using) to be released and possibly deallocated.