Re: Is Apple's singleton sample code correct?
Re: Is Apple's singleton sample code correct?
- Subject: Re: Is Apple's singleton sample code correct?
- From: Shaun Wexler <email@hidden>
- Date: Fri, 2 Dec 2005 16:19:12 -0800
On Dec 2, 2005, at 3:24 PM, Dietmar Planitzer wrote:
What is the sound and important technical reason for overriding the
reference counting methods in the case of a singleton ?
To prevent it's accidental deallocation, when no other objects happen
to be retaining it. Secondary reason would be that ref-counting
methods are expensive, and for example in the case of NSNull, being
repeatedly retained when inserted and released when removed from
collections is highly-unnecessary overhead; by overriding ref-count
methods, that overhead reduces to a method dispatch. Foundation and
certain AppKit objects maintain a local refcount ivar for
efficiency. Objects normally have an implied refCount of 1, and
additional references are recorded in a maptable (ie dictionary)
keyed by the object's id; it's not cheap.
Could you please give me a sound technical reason why overriding -
dealloc in the case of a singleton so that it does nothing is
supposed to be a good idea ?
To prevent it's accidental deallocation. If the object MUST persist,
such as when its functionality is critical to the operation of the
app, then -dealloc should be NOP'ed. Again, these measures are
intended for immortal "hardcore" singletons; there are many other
flavors than plain vanilla.
I personally think that it is not only unnecessary and that it
needlessly complicates the code base, but I also think that it
makes it unnecessarily harder to find a memory management bug in
the code that is using the singleton.
Not at all. If it is an immortal singleton, either it will persist
until the app's threads are terminated and all memory zones are
freed, or you tell the singleton to go away (manually).
The reason why I think that doing this is not a good idea is that
code which calls a -dealloc method directly, no matter on what
object, severely violates the CMM rules. Thus, I should be able to
find this problem efficiently and in short order. But overriding -
dealloc so that it does nothing makes it unnecessarily hard for me
to find this problem as it gets swept under the rug. At least, when
you really want to write your code that way, make sure that dealloc
raises an appropriate exception so that we get a chance at fixing
code that is using the singleton in an inappropriate way.
Exactly.
Well, I think that the sample code should concentrate on the core
issue of writing a singleton. I don't think that it's such a good
idea that it drags side issues like multi threading in which has
nothing to do with the general and basic question of how a
singleton is typically implemented in the case of Cocoa. It
needlessly complicates the sample code and distracts from the
actual problem. This is in fact the reason why I have dropped the
thread-safety stuff altogether in my code. It just distracts.
Multithreading is the heart of Mac OS X. App's which only run single-
threaded when there is an opportunity for multitasking are dragging
down Apple and the Macintosh platform. Remember that just because
you write your code "single-threaded", it doesn't mean that a plug-in
or framework won't create additional threads in your process: APE,
for example. CoreAudio, MIDI, QuickTime. AppKit threads for pulsing
Aqua buttons.
Hmm, please give me a sound technical explanation why you think
that the double-check locking idiom works reliably in ObjC.
I don't like that aspect of Apple's sample code either, and I agree
that it's flawed. A singleton should only be created by ONE method,
ie +sharedWhatever, and +allocWithZone: should return [self
sharedWhatever], and it must all be thread-safe. My example classes
satisfy this. SKWSingletonObject prevents re-init, and
MortalSingleton does not. However subclasses could easily prevent re-
init, perhaps like this:
- (id)init
{
@synchronized(singletons) {
if ([singletons objectForKey:[self class]]) {
return self;
}
}
/* init here */
return self;
}
Honestly I don't know why you call this thread entirely too silly.
The only problem that I see with this thread is that at the
beginning there was a very simple question. However, although a lot
has been said in this thread, and a lot of topics have been brought
up that have absolutely nothing to do with the original question,
so far nobody has given a simple, clear and sound technical
explanation why it is necessary to override the reference counting
methods.
To prevent a singleton's accidental deallocation, and/or to optimize
collection insertion/deletion, etc.
Note that I said, necessary. Since quite a number of people have
sided with the Apple sample code, I have to assume that there must
be a really important reason that it overrides -retain, -release
and -autorelease and that by doing so it achieves something really
important that would not be achievable by implementing the
singleton using the standard CMM rules like I did in my code.
So please, could someone answer this simple question : What is the
seemingly so important advantage of overriding the reference
counting methods ?
Or formulated in a different way: why should the implementation of
a singleton not follow the standard CMM rules ?
And just to make it clear: I'm not going to accept answers like, it
makes ref counting faster or it makes it possible to violate the
CMM rules in the implementation of the singleton's +alloc and -copy
methods, or that is how NeXT did it. I'm sorry, but those are not
sound technical reasons for me.
I guess you need to tell us the answer then, because you're
apparently disinclined to accept the answers so given.
--
Shaun Wexler
MacFOH
http://www.macfoh.com
"I refuse to answer that question on the grounds that I don't know
the answer." -- Douglas Adams
_______________________________________________
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