hi there,
so I recently tried to create a class as a singleton. Unfortunatly, it seems it isn't work as it should.
So what I did is this (I did it this way because I didn't want to use a sharedManager-method like in the example on apples page)
Code:
@implementation MyClass
static MyClass *singletonInstance = nil;
static BOOL singletonCreated = NO;
- (id)init
{
@synchronized (self) {
if (singletonCreated == NO) {
if (self = [super init]) {
self.title = @"Title";
// Some initialiaztion stuff that should be done once
}
singletonCreated = YES;
}
}
return self;
}
// Some other stuff here
+ (id)allocWithZone:(NSZone *)zone { //let alloc always return the same instance
@synchronized(self) {
if (singletonInstance == nil)
singletonInstance = [super allocWithZone:zone];
}
return singletonInstance;
}
- (id)copyWithZone:(NSZone *)zone { return self; } //copy is not possible
- (id)retain { return self; } //retain is not possible
- (unsigned)retainCount { return UINT_MAX; } //means that this object cannot be released
- (void)release {} //release is not possible
- (id)autorelease { return self; } //autorelease is not possible
So ... the problem seems to be that the @synchronized lock doesn't seem to work at all.
What I read is that, if a @synchronized block gets executed twice at the same time, the execution that started later waits until the execution that started earlier is done and then executes the code.
It doesn't work.
In my application, the init-method gets executed twice simultaniously and both times the method gets executed.
So what actually happens is:
alloc is called, creates an instance of the class and saves that instance to singletonInstance.
now init is called and starts executing.
At the beginning of the execution of init, alloc gets called again (from another thread) and returns singletonInstance (like it should).
In the middle of the execution of init, init gets called again. What it SHOULD do is it should wait until that first execution of init is finished. It does not. it gets executed while that other execution of init is already running ... which leads to unpredictable results because my initalization code (so initialization of variables and whatnot) is executed twice.
any ideas why this happens?
since I make intense use of singletons in my application and I often have initialization code in my init-method that should only get executed once for that singleton I have to get that to work
thanks