RE: Singletons with ARC
RE: Singletons with ARC
- Subject: RE: Singletons with ARC
- From: Abdul Sowayan <email@hidden>
- Date: Fri, 09 Dec 2011 00:18:11 -0500
- Thread-topic: Singletons with ARC
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@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