Re: Synthesised properties and additional actions
Re: Synthesised properties and additional actions
- Subject: Re: Synthesised properties and additional actions
- From: Ken Thomases <email@hidden>
- Date: Wed, 22 Jun 2011 14:44:22 -0500
On Jun 22, 2011, at 1:49 PM, Ken Tozier wrote:
> For those of us new to @synthesize, would it be possible to get concrete examples of exactly what it does to create "thread safety? What is Apple doing, under the hood, to provide this?
Well, obviously, that's an implementation detail. Any explanation has to be caveated out the wazoo that we don't really know and, if we did, it could change at any time. Consider yourself caveated.
> For example: Say I have 3 properties, a float, a struct and an NSObject subclass. Written by hand they might look like
>
> - (void) setScalar:(float) inValue
> {
> floatProp = inValue;
> }
>>
> - (void) setObject(id) inValue
> {
> objectProp = inValue;
> }
For the above two, if you're using managed memory and the object property is merely "assign", nothing would be necessary on any likely CPU architecture. (I'm not really familiar with ARM, but I'd be surprised if the above weren't atomic.) If you're using GC, what's apparently a simple assignment in the object case isn't any longer. The compiler emits a write barrier. I'm not sure what the atomicity implications of that are.
> - (void) setStruct:(MyStruct) inValue
> {
> structProp = inValue;
> }
The issue here is that two threads might simultaneous be running -setStruct:. Or, one thread might be running -struct (the getter) while -setStruct: is running in another. Assuming a non-trivial struct, the CPU will be using multiple instructions to copy the fields of the struct. The threads can be interrupted at any point. So, a getter might get half of the old struct and half the new. Or the two setters could overwrite each other -- the first thread writes part of the struct and is interrupted, the second thread writes over the entire struct, the first thread resumes and finishes writing what it didn't get to previously. So, the instance variable contains a mishmash of values, some from the first thread's copy and some from the second thread's.
The above explanation is somewhat simplified. There can be more than two threads. Both the compiler and the CPU can do wholly non-intuitive things to your code and its effects. Etc.
> If for some reason, we have to write accessors for some properties, what might those three look like if we could look into the source of properties created by synthesize?
You would want the getter and the setter to use a shared lock to make sure that only one is running at a time and to counteract some of the non-intuitive stuff done by the compiler and CPU.
For example:
- (MyStruct)struct
{
@synchronized(self) {
return structProp;
}
}
- (void) setStruct:(MyStruct)inValue
{
@synchronized(self) {
structProp = inValue;
}
}
Now, @synchronized is fairly expensive. You could use NSLock for some speed improvement. Apparently, synthesized accessors use an even more efficient lock.
Also, I have synchronized on the object (self). If the other atomic properties use the same mechanism, then they are all synchronized with each other, which is not strictly necessary for the atomicity of each property in isolation. That means there will be more contention around that shared lock than is necessary, which is also inefficient. If you use NSLock, you could use a separate lock object for each atomic property, which is more efficient. And, again, synthesized accessors do something like that.
All of that said, keep in mind Apple's advice that atomic properties are _not_ sufficient for general thread safety. They only protect against a certain narrow thread safety issue. There are many others, which almost always require synchronization mechanisms at a high level of the design of your classes.
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden