• 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 Apple's singleton sample code correct?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is Apple's singleton sample code correct?


  • Subject: Re: Is Apple's singleton sample code correct?
  • From: Shawn Erickson <email@hidden>
  • Date: Sat, 26 Nov 2005 00:14:19 -0800


On Nov 25, 2005, at 7:50 PM, David Gimeno Gost wrote:

On 25 Nov 2005, at 19:05, Shawn Erickson wrote:

Consider reviewing what I use...

<http://www.cocoadev.com/index.pl?FTSWAbstractSingleton>

I don't get it, sorry.

I was answering in the point of view of an implementation like the one Apple outlines in the documentation you noted. The one I use moves init out to an initSingleton method that is private and not advertised in headers (note the version of the website was simplified, normally I have initSingleton in a private category in the .m file).


Anyway it wasn't clear to me the alternate implementation that you had in your head so I couldn't talk to that.

1. If I wanted to allow getting the singleton instance variable through [[alloc] init] calls, then I would write +allocWithZone: as follows:

+ (id) allocWithZone: (NSZone*) zone
{
    @synchronized( self ) {
        if ( sharedInstance == nil ) {
            sharedInstance = [super allocWithZone: zone];
        } else {
            [sharedInstance retain];
        }
    }
    return sharedInstance;
}

This will work correctly regardless of whether the -retain and - release methods are overridden or not. Moreover, it encourages client code to send a -release message to any singleton instance it gets through [[alloc] init], as it is supposed to do with any object returned by such methods, because failure to doing so can be detected with the aid of debugging tools, as for any other resource leak.

This is sufficient to ensure that memory for only one object is allocated [1] on the first attempt and for all other attempts an synthetic "allocation" takes place by adding a retain. What it doesn't prevent against is the possibility of the singleton being deallocated since code that does [[mySingleton alloc] init] will send the "allocated" instance a release or autorelease message since they are expected to follow the memory contract.


[1] At least when using normal messaging to the class to allocate an instance.

If you changed your code to the following you could prevent your singleton from being deallocated (assuming no one breaks the memory contract).

+ (id) allocWithZone: (NSZone*) zone
{
    @synchronized( self ) {
        if ( sharedInstance == nil ) {
            sharedInstance = [super allocWithZone: zone];
        }
    }
    return [sharedInstance retain];
}

You can think of the implicit retain coming from [super allocWithZone] as being the one related to the reference you are stashing in sharedInstance and the explicit retains related to allocate from the callers point of view... in other words the use of "sharedInstance" and its related retain is an internal detail not one to be touched by external memory management.

2. The -retain and -release methods shouldn't be overridden. There is no point in doing so and the way it is done in the current sample code guarantees that code breaking Cocoa's memory management rules will go by unnoticed.

Correct they don't need to be overridden assuming you do something like you did in your code above. I would however likely throw an exception if somehow dealloc got called. This would be an active way of detecting an over release scenario, at least possibly a little closer to the source. An over retain or under release case will not be detected since no memory leak would exist as a result, you would have to watch retain counts and understand code to do that.


You may want to consider overriding retainCount to return UINT_MAX, at least in release build, since I believe some optimization is done by framework code when seen.

-Shawn


_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Follow-Ups:
    • Re: Is Apple's singleton sample code correct?
      • From: David Gimeno Gost <email@hidden>
References: 
 >Is Apple's singleton sample code correct? (From: David Gimeno Gost <email@hidden>)
 >Re: Is Apple's singleton sample code correct? (From: Shawn Erickson <email@hidden>)
 >Re: Is Apple's singleton sample code correct? (From: David Gimeno Gost <email@hidden>)

  • Prev by Date: Re: Subversion and XCode
  • Next by Date: Re: Subversion and XCode
  • Previous by thread: Re: Is Apple's singleton sample code correct?
  • Next by thread: Re: Is Apple's singleton sample code correct?
  • Index(es):
    • Date
    • Thread