• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: is this enough for a singleton? (for a class cluster "placeholder")
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: is this enough for a singleton? (for a class cluster "placeholder")


  • Subject: Re: is this enough for a singleton? (for a class cluster "placeholder")
  • From: Shaun Wexler <email@hidden>
  • Date: Fri, 13 Feb 2004 08:08:38 -0800

On Feb 11, 2004, at 1:22 PM, Ben Dougall wrote:

i got this code from the archives for a singleton object:

+ (id)allocWithZone:(NSZone *)zone {
if ([MyAbstractClass self] == self)
return NSAllocateObject([MyConcreteClass self], 0, zone);
return [super allocWithZone:zone];
}

don't quite understand it -- will that give an ok/perfectly fine singleton implementation? usually the singleton implementations that i've seen involve a static variable in the class, but i know there's a variety of ways to do singletons. is there something else that needs to be done further to the above code, or is that it, so far as the singleton aspect of it goes?

(not sure if this throws a different light on it or not -- both the above code and what i want a singleton for, is for the abstract class of a class cluster - a placeholder - the thing that vends as it were. the above code is from here: <http://cocoa.mamasam.com/COCOADEV/2001/09/2/12499.php>)

thanks, ben.

One of the problems with a lot of the different singleton base-classes you'll see is that you can still call the singleton method -init. Unless each subclass has strict preventative measures to disallow reentrance (which most init methods don't implement), then the singleton can be broken accidentally. My "hardcore" singleton class is fairly bulletproof; it "swizzles" each subclass init method IMP, to prevent it from accidentally being called again and corrupting the singleton instance. I'll attach the .m below.

For efficiency, give each of your subclasses their own class accessor/instantiation method, such as this:

+ (id)sharedSerialPortRegistry
{
static id sharedSerialPortRegistry = nil;
if (!sharedSerialPortRegistry) {
sharedSerialPortRegistry = [self sharedInstance];
}
return sharedSerialPortRegistry;
}
-- Shaun Wexler
MacFOH
http://www.macfoh.com


/ *======================================================================= =====================*/
//
// SKWSingletonObject.m
// SKWBase
//
// Created by Shaun Wexler on Sun Aug 31 2003.
// Copyright (c) 2003 SKW Development. All rights reserved.
//
/ *======================================================================= =====================*/

#import "SKWSingletonObject.h"
#import <objc/objc-runtime.h>

@implementation SKWSingletonObject

static NSMutableDictionary *sharedInstances = nil;
static NSRecursiveLock *sharedInstancesLock = nil;
static Method abstractInit = NULL;
static Method disabledInit = NULL;

+ (void)initialize
{
@synchronized(self)
{
if (!sharedInstances) {
sharedInstances = [[NSMutableDictionary alloc] init];
sharedInstancesLock = [[NSRecursiveLock alloc] init];
abstractInit = class_getInstanceMethod(self, @selector(init));
disabledInit = class_getInstanceMethod(self, @selector(singletonInitDisabled));
}
}
}

+ (id)sharedInstance
{
Class class = [self class];
id singleton = nil;

@try {
[sharedInstancesLock lock];
singleton = [sharedInstances objectForKey:class];
if (!singleton) {
singleton = class_createInstanceFromZone(class, 0U, [self zone]);
if (singleton) {
Method singletonInit = class_getInstanceMethod(class, @selector(init));
[sharedInstances setObject:singleton forKey:class];
if (singletonInit) {
[singleton init];
if (singletonInit->method_imp != abstractInit->method_imp) {
singletonInit->method_imp = disabledInit->method_imp;
}
}
}
}
}
@catch (NSException *exception) {
NSLog(@"%@ raised %@: %@", class, [exception name], [exception reason]);
}
@finally {
[sharedInstancesLock unlock];
}

return singleton;
}

- (id)singletonInitDisabled
{
[NSException raise:NSInternalInconsistencyException
format:@"can't re-init %@ sharedInstance", [self class]];

return self;
}

+ (id)new
{
return [self sharedInstance];
}

+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}

+ (id)alloc
{
return [self sharedInstance];
}

- (id)init
{
return [super init];
}

- (id)copy
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)copyWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)mutableCopy
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (id)mutableCopyWithZone:(NSZone *)zone
{
[self doesNotRecognizeSelector:_cmd];
return self;
}

- (unsigned)retainCount
{
return UINT_MAX;
}

- (oneway void)release
{
}

- (id)retain
{
return self;
}

- (id)autorelease
{
return self;
}

- (void)dealloc
{
[self doesNotRecognizeSelector:_cmd];
}

@end
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: is this enough for a singleton? (for a class cluster "placeholder")
      • From: Shawn Erickson <email@hidden>
References: 
 >is this enough for a singleton? (for a class cluster "placeholder") (From: Ben Dougall <email@hidden>)

  • Prev by Date: XCode const warnings
  • Next by Date: Re: XCode const warnings
  • Previous by thread: Re: is this enough for a singleton? (for a class cluster "placeholder")
  • Next by thread: Re: is this enough for a singleton? (for a class cluster "placeholder")
  • Index(es):
    • Date
    • Thread