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: David Gimeno Gost <email@hidden>
- Date: Fri, 2 Dec 2005 06:47:57 +0100
On 2 Dec 2005, at 02:38, mmalcolm crawford wrote:
Actually I've always had both approaches in mind and I've strived to
not make this explicit until now on purpose.
This frankly beggars belief.
Yes, you're right. "Always" here meant since I was told to use
notifications instead of -dealloc. I had nothing about this in mind
when I started this thread.
This far into the thread and we suddenly find that you haven't even
fully described your pattern. The very fact that you appear to have
been unable to clearly articulate and prove either your problems with
the current pattern or your proposed solution speaks volumes
Well, I thought I had stated clearly that Uli Kusterer had already done
it, so I considered it more appropriate to refer to his implementation
rather than proposing it as if it was mine, but here it is if that's
the problem (minor changes made and comments added, let me know if
there is something wrong about making the changes):
@implementation MySingleton
+ (MySingleton*) sharedInstance
{
static MySingleton* sSharedInstance = nil;
@synchronized( self ) {
if ( sSharedInstance == nil ) {
// Note: calls -singletonInit instead of -init
sSharedInstance = [[MySingleton alloc] singletonInit];
}
}
return sSharedInstance;
}
- (id) init
{
// If we got here, the instance was created by alloc/init
// instead of +sharedInstance. Discard it and return the
// one created by +sharedInstance instead.
// Send a retain message to account for the
// call to alloc/init made by the client.
[self release];
self = [MySingleton sharedInstance];
return [self retain];
}
- (id) singletonInit
{
self = [super init];
if ( self != nil ) {
// Your singleton initialization goes here.
// This method will never be called more than once
// for the same object.
}
return self;
}
@end
You have not explained how any of these alleged "nasty side effects"
manifest themselves.
Whenever you expect -dealloc to be be invoked. Whenever you override
-init following the convention shown in "The Objective-C Programming
Language" (i.e. not taking into account the fact that it could be
called more than once for the same object). Whenever you copy/paste
buggy code that uses the singleton as any other object and reuse it for
use with an object that's not a singleton.
(Here, history is relevant, in that in over a decade of using this
pattern I cannot recall any occasion when it has caused any of the
problems you suggest
http://www.cocoabuilder.com/archive/message/cocoa/2005/11/28/151235
From the consumer perspective, complexity is not affected.
The perspective I'm talking about is the writer of the singleton.
"Safety decreases" is a nebulous charge whose meaning is unclear
It requires the writer of the singleton to remember to take into
account that -init may be called more than once for the same object,
something very easy to forget and very easy to remain undetected
because client code may actually never call alloc/init... until someday
someone thinks it could actually be a good idea.
It allows code that doesn't follow the memory management rules to go by
unnoticed. I consider this a problem.
if anything, though, safety is increased since the singleton cannot be
prematurely disposed of (it's particularly unclear how you intend to
prevent this...).
It follows from just requiring the client to follow Cocoa's memory
management rules.
Moreover, you have still not, as far as I can tell, clearly and simply
explained what your replacement would be (see below).
I've repeatedly stated that Uli had already done it (see above).
You talk vaguely about the possibility of allowing for the dealloc
method to be called, as if this is a silver bullet.
This is no silver bullet for anything. It just lets developers to
choose the approach that best fits their needs, or their programming
style, or the way they want to think about their objects. There is no
point in removing the ability to choose just for the sake of it.
It remains unclear how you intend to ensure that the singleton is
deallocated only when it is guaranteed not to be needed again.
It is automatically ensured by just requiring client code to follow the
memory management rules.
*dealloc should _not_ be used as the locus of code for doing general
resource reclamation.* Other current threads have indicated why this
might be the case (see, for example,
<http://lists.apple.com/archives/Cocoa-dev/2005/Nov/msg02113.html>).
Actually, I already had this in mind and considered it a reason to use
-dealloc for resource deallocation until garbage collection becomes
available. Let me elaborate:
We cannot think of -finalize as a -doCleanUp method, because what
really makes it special is that it will be _automagically_ called when
the garbage collector determines that no other object keeps a reference
to the instance. The closest we can get to this behavior without GC is
to rely on -dealloc being called when all retained references to the
object are released. This would make it easier to modify the code to
take advantage of garbage collection when it becomes available,
wouldn't it?
**** The following is is the important piece: ****
Please describe and show an implementation of the solution you
propose. The current document basically describes two patterns (a
"simple" singleton and a "true" singleton) in about three short
paragraphs and 20 so lines of code. You've written many times this
amount in the thread. It should be trivial, then, to provide a
solution that:
Is easy to understand
Is simple to implement
Allows dealloc to be called
Ensures that dealloc is not called prematurely (to avoid expensive
re-instantiation)
Prevents access of a freed object
Allows clients to abide by Cocoa's memory management rules
Allows the singleton to be accessed from any part of the application,
without assuming an application architecture beyond that supplied by
Cocoa
Does not impose a particular application architecture on the client
Let me know if you believe the above implementation fails to satisfy
any of those requirements.
If you can do this, it can then be subjected to proper scrutiny and
the debate can move forward in a useful and constructive fashion.
Until then it's like tilting at ethereal windmills...
Please, note that this was already done several days ago:
http://www.cocoabuilder.com/archive/message/cocoa/2005/11/26/151142
If you wonder why this thread has gone "tilting at ethereal windmills"
instead of "move forward in a useful and constructive fashion" for so
long, you'll have to ask those that have kept arguing with me instead
of taking a look at this implementation. :-)
Regards.
_______________________________________________
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