On Sat, Apr 16, 2011 at 8:04 PM, WT <jrca...@gmail.com> wrote: > From the testing I've done - creating several threads, each invoking either > [MySingleton sharedInstance] or [[MySingleton alloc] init] after a randomly > selected sleep time, and running the test anew several times - it appears to > behave correctly, that is, the same instance is used in every thread, it's > always properly initialized (all "instances" have the same value for > someInteger), and each of the three dispatch_once() blocks is executed > exactly once, no matter how many threads were created.
Do you really need a singleton, or just a default instance? For example, NSFileManager has a default instance, but you can still alloc/init your own if you want. If all you need is a shared instance, then this will work just dandy for any class: + (id)sharedInstance { static id sharedInstance; static dispatch_once_t once; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } As for your code: > // MySingleton.h: > > #import <Foundation/Foundation.h> > > @interface MySingleton: NSObject > { > NSUInteger someInteger_; > } > > @property (readwrite, nonatomic, assign) NSUInteger someInteger; > > + (MySingleton*) sharedInstance; > > @end > > // MySingleton.m: > > #import <dispatch/dispatch.h> > #import "MySingleton.h" > #import <stdlib.h> > #import <time.h> > > static MySingleton* stSharedInstance = nil; > > static dispatch_once_t stSharedInstanceInvoked; > static dispatch_once_t stAllocWithZoneInvoked; > static dispatch_once_t stInitInvoked; All of these could be made static variables within the method body, increasing readability and reducing pollution of the global scope without affecting storage longevity. > > @implementation MySingleton > > @synthesize someInteger = someInteger_; > > > + (MySingleton*) sharedInstance; > { > dispatch_once(&stSharedInstanceInvoked, > ^{ > NSLog(@"+sharedInstance block entered"); > > // Assignment done in +allocWithZone:. > // The autorelease message is sent to prevent XCode's > // static analyzer from issuing a warning about a possible > // memory leak. There is no leak, since the singleton is > // not meant to be deallocated, and the autorelease message > // does nothing, as per its overridden implementation below. Rather than relying on -allocWithZone: to return the shared instance, why not assign to stSharedInstance here? > > [[[[self class] alloc] init] autorelease]; You are in a class method. self == [self class], so no need to call +class here. > > NSLog(@"+sharedInstance block exited"); > }); > > return stSharedInstance; > } > > > + (id) allocWithZone: (NSZone*) zone; > { > dispatch_once(&stAllocWithZoneInvoked, > ^{ > NSLog(@"+allocWithZone: block entered"); > > stSharedInstance = [super allocWithZone: zone]; > > NSLog(@"+allocWithZone: block exited"); > }); > > return stSharedInstance; Of course this means you can't subclass this class. > } > > > - (id) init; > { > __block id tempSelf = self; Because the block is not going to be copied, you do not need to worry about creating a __block version of self here. And since this is a singleton, even if the block *were* copied (and thus self retained), you still wouldn't care. > > dispatch_once(&stInitInvoked, > ^{ > NSLog(@"-init block entered"); > > tempSelf = [super init]; > > if (tempSelf) > { > someInteger_ = random() % 1000; > NSLog(@"Instance initialized"); > } > > NSLog(@"-init block exited"); > }); > > self = tempSelf; > return self; > } > > > - (id) copyWithZone: (NSZone*) zone; > { > return self; By virtue of this implementation, you can't implement NSCopying in a subclass. But you can't subclass this class anyway because of +allocWithZone:. > } > > > - (id) retain; > { > return self; > } > > > - (unsigned) retainCount; > { > return UINT_MAX; // Denotes an object that cannot be released. Why bother? All this will do is mask any bugs where your singleton disappears. > } > > > - (void) release; > { > /* do nothing */ Don't do this. As above, you're just masking cases where you accidentally over-release your singleton. > } > > > - (id) autorelease; > { > return self; > } Look, you're going to great lengths to ensure you never create more than one instance of this class. Is any of it really necessary? --Kyle Sluder _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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 arch...@mail-archive.com