Hi Ben,
>I'm rather confused by the commonly used implementation of singletons.
>(Ignoring the fact that perhaps I shouldn't be using singletons) I would
>appreciate you view on this.
>
>Normally I implement a singleton such as..
>
>static MyClass *sharedInstance = nil;
>+ (MyClass *)sharedInstance
>{
> @synchronized(self)
> {
> if (sharedInstance == nil)
> sharedInstance = [[self alloc] init];
> }
> return(sharedInstance);
>}
The above will still work in an ARC environment. It is rather inefficient,
however. For details please check the "Double Check Locking Optimization
pattern":
http://www.cs.wustl.edu/~schmidt/PDF/DC-Locking.pdf
The reason it is inefficient is that locking (mutexes, or @synchronized above)
is expensive. And you incur that expense every single time you call
sharedInstance method.
A better way to write that method is below:
+ (MyClass *)sharedInstance
{
static MyClass *sharedInstance = nil;
if(sharedInstance == nil)
{
@synchronized(self)
{
if (sharedInstance == nil)
sharedInstance = [[self alloc] init];
}
}
return sharedInstance;
}
The above is a lot more efficient. It does not incur the cost of locking
(mutex, or @synchronized) every single time. It is thread safe. Read the paper
for detailed analysis.
>This has fared me well over the years.
>
>With the introduction of ARC, I assumed there might be a more suitable
>implementation out there, and I found this common snippet of code commonly on
>the net.
>
>+ (MyClass *)sharedInstance
>{
> static MyClass *sharedInstance = nil;
> static dispatch_once_t onceToken;
> dispatch_once(&onceToken, ^{
> sharedInstance = [[MyClass alloc] init];
> // Do any other initialisation stuff here
> });
> return sharedInstance;
>}
Yes, the above looks correct.
>Which confuses me because surely it should look more like.
>
>static MyClass *sharedInstance = nil;
>+ (MyClass *)sharedInstance
>{
> if(sharedInstance==nil){
> static dispatch_once_t onceToken;
> dispatch_once(&onceToken, ^{
> sharedInstance = [[MyClass alloc] init];
> // Do any other initialisation stuff here
> });
>}
> return sharedInstance;
>}
>
>...else otherwise the second time I access the singleton, MyClass *
>sharedInstance is declared a second time and set to nill, removing the first
>instance from memory under ARC?
No, the second time sharedInstance is called it will NOT be set to nil. This is
more of a C/C++ detail. It will not be set to nil again because the variable is
static.
try the following in Xcode and you will see :-)
-(void) callMe
{
static int i = 0;
NSLog(@"value before increment is: %d, i);
++i;
NSLog(@"value after increment is: %d, i);
}
Invoke "callMe" several times and you will see that it keeps incrementing i. So
you will see
value before increment is: 0
value after increment is: 1
value before increment is: 1
value after increment is: 2
value before increment is: 2
value after increment is: 3
Thanks,
Abdul
_______________________________________________
Cocoa-dev mailing list ([email protected])
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]