Since Kendall posted a threadsafe singleton that attempts to avoid locking costs, I thought I would toss one up as well:
#import
static void * volatile sharedInstance = nil;
+ (className *) sharedInstance {
while (!sharedInstance) {
className *temp = [[self alloc] init];
if(!OSAtomicCompareAndSwapPtrBarrier(0x0, temp, &sharedInstance)) {
[temp release];
}
}
return sharedInstance;
}
Okay, let me explain how this works:
Fast case: In normal execution sharedInstance
has already been set, so the while
loop is never executed and the function returns after simply testing for the variable's existence;
Slow case: If sharedInstance
doesn't exist, then an instance is allocated and copied into it using a Compare And Swap ('CAS');
Contended case: If two threads both attempt to call sharedInstance
at the same time AND sharedInstance
doesn't exist at the same time then they will both initialize new instances of the singleton and attempt to CAS it into position. Whichever one wins the CAS returns immediately, whichever one loses releases the instance it just allocated and returns the (now set) sharedInstance
. The single OSAtomicCompareAndSwapPtrBarrier
acts as both a write barrier for the setting thread and a read barrier from the testing thread.