Results 1 to 5 of 5

Your favorite Apple, iPhone, iPad, iOS, Jailbreak, and Cydia site.


Thread: Singleton/Lock not working

  1. #1
    Default Singleton/Lock not working
    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
    Last edited by BlackWolf; 2008-04-14 at 01:14 PM.

  2. #2
    SDK or toolchain?

    I'd guess @synchronized isn't supported. I suppose if you really want this, you can use a mutex. I'd also guess this is what @synchronized would do if it worked.

  3. #3
    Quote Originally Posted by Cobra View Post
    SDK or toolchain?

    I'd guess @synchronized isn't supported. I suppose if you really want this, you can use a mutex. I'd also guess this is what @synchronized would do if it worked.
    SDK, sorry I forgot to mention that. according to apple @synchronized is supported (otherwise I would get some kind of compiler error, wouldn't I?) and yeah, it does the same as a mutex. I guess I'll try a mutex, I just think @synchronized is much better readable than using a mutex, but maybe it works if I use a mutex ... thanks for the reply.

    anyway, I encountered another (bigger) problem with threads, maybe you (or anyone else) can help me out there: in my application delegate class I have something like
    Code:
    MyClass *myClass = [[MyClass alloc] init];
    //some stuff
    [self.window addSubview:myClass.view];
    whereas MyClass is a subclass of UIViewController.
    my problem is: while MyClass alloc and MyClass init are executed, cocoa still proceeds with the code posted above. this leads to problems because it reaches the addSubview-line before MyClass init is finished. Since the init-method of MyClass sets some instance variables that are needed to show the view properly this leads into trouble.
    any idea how to avoid this? I don't even think this is normal behaviour, is it? I mean, multithreading is super, but shouldn't MyClass be properly initalized after
    MyClass *myClass = [[MyClass alloc] init];
    ? why is this running in a seperate thread? how do I avoid this?

    thanks
    Last edited by BlackWolf; 2008-04-14 at 11:24 PM.

  4. #4
    Maybe @synchronized is a SDK bug... I'm more familiar with the toolchain and threading, so don't know more.

    Quote Originally Posted by BlackWolf View Post
    anyway, I encountered another (bigger) problem with threads, maybe you (or anyone else) can help me out there: in my application delegate class I have something like
    Code:
    MyClass *myClass = [[MyClass alloc] init];
    //some stuff
    [self.window addSubview:myClass.view];
    whereas MyClass is a subclass of UIViewController.
    my problem is: while MyClass alloc and MyClass init are executed, cocoa still proceeds with the code posted above. this leads to problems because it reaches the addSubview-line before MyClass init is finished. Since the init-method of MyClass sets some instance variables that are needed to show the view properly this leads into trouble.
    any idea how to avoid this? I don't even think this is normal behaviour, is it? I mean, multithreading is super, but shouldn't MyClass be properly initalized after
    MyClass *myClass = [[MyClass alloc] init];
    ? why is this running in a seperate thread? how do I avoid this?

    thanks
    Err, what?

    This is one of those times that makes me say... I doubt it's doing what you think. What makes you think it is running in a different thread? A single method doesn't switch threads within it's own code.

  5. #5
    Quote Originally Posted by Cobra View Post
    Maybe @synchronized is a SDK bug... I'm more familiar with the toolchain and threading, so don't know more.



    Err, what?

    This is one of those times that makes me say... I doubt it's doing what you think. What makes you think it is running in a different thread? A single method doesn't switch threads within it's own code.
    I doubt that as well, but I can't think of another explanation

    What makes me think that it is running in a seperate thread is that loadView of MyClass is executed while init is still running. So loadView is executed before init finished executing.
    I started to notice something is wrong because some instance variables I set in init are nil in loadView (which shouldn't be the case if init did what it is supposed to do - set them to a value). So I set two breakpoints: one at the beginning of init and one at the beginning of loadView. The first BP reached is the one at the beginning of init (logically). Now in the middle of init suddenly the second BP - so the one at the beginning of loadView - is reached. The only explanation I have for that is that init is running in a seperate thread and when the code I posted reaches the addSubview-line the loadView-method is invoked.
    The only other explanation I have would be if init somehow invoked loadView itself, but I can't see how that should be possible.

    But I have some spare time later, I will check it again and see if I can find another explanation for this.

Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •