Disclaimer: code in this answer is not tested!
First of all I'd like to mention that most pointer uses don't really need compare-and-swap. C pointer reads and writes are atomic by themselves. See this SO answer for more detail. Same goes for ARM. So if you implement atomic getters and setters you only need a memory barrier to guarantee that other threads see fully initialized objects:
NSObject * global;
NSObject * get() { return global; }
void set(NSObject * value) { OSMemoryBarrier(); global = value; }
Now back to the question, because who knows, maybe there are real uses for compare-and-swapping objects. The casts are still possible, you just declare them differently now:
NSString * a = @"A";
NSObject * b = @"B";
OSAtomicCompareAndSwapPtrBarrier(
(__bridge void *)a,
(__bridge void *)b,
(__bridge void * *)&a);
However this code has a problem: the string @"A"
loses a reference, and @"B"
gets referenced twice, without ARC knowing. Therefore @"A"
will leak, and the program will likely crash when leaving the scope because @"B"
will be released twice while only having the retain counter of 1
.
I think the only option is to use Core Foundation objects. You can use the fact that NSObject is toll-free bridged with CFType. I couldn't find any definitive documentation on this but it follows from common sense and practical evidence. So e.g. it is possible to implement a singleton:
CFTypeRef instance;
Thingamabob * getInstance() {
if (!instance) {
CFTypeRef t = (__bridge_retained CFTypeRef)[Thingamabob new];
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, t, &instance)) {
CFRelease(t);
}
}
return (__bridge Thingamabob *)instance;
}