eugene
eugene

Reputation: 41765

(iphone) having NSThread* as member variable is a bad idea?

One of my custom class has NSThread* as member variable.

I'm letting the thread exit by setting a variable(isNeedToExit).
Then call a release on the thread object [myThread release];

I intended the thread to exit first and release call gets called.
But on second thought, release call might get called before the thread notices the boolean value changed and exit.
(Because the thread is not constantly looking at the value to see if it needs to exit)

@property (nonatomic, retain) NSThread* myThread;

- (void) dealloc
{
   ...
   [myThread release];
   myThread = nil;
   ...
   [super dealloc];
}

- (id) initMyClass
{
   if(self = [super init] )
   {
      ...
      NSThread* aThread = [[NSThread alloc] initWithTarget: self selector:@selector(theThreadMain) object: nil];
      self.myThread = aThread;
      [aThread release];
      [self.myThread start];
      ..
   }
   return self;
}

- (void) theThreadMain
{   
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    // Add your sources or timers to the run loop and do any other setup.                                                                                                                                                                   
    NSRunLoop *runloop = [NSRunLoop currentRunLoop];
    [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

    do
    {
        // Start the run loop but return after each source is handled.                                                                                                                                                                      
        SInt32    result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES);

    }
    while (self.isNeedToExit == false);

    [pool release];

    SYSLOG(LOG_DEBUG, "thread exiting");
}

I thought of moving [myThread release] call (now at the class's dealloc) to last line of theThreadMain..

Not sure if this is the correct way to stop a thread when it is a member variable of another class.

Thank you

Upvotes: 0

Views: 582

Answers (1)

Darren
Darren

Reputation: 25619

Actually, your initial assumption was more correct. Your current implementation, however, will not work because dealloc will never be called.

Your class is retained by NSThread in initWithTarget:selector:object and will not be released until the thread finishes executing. Therefore, your class instance will not be deallocated as long as the thread is executing.

One way to solve the problem is to add a "cancel" method to your class that stops the thread. E.g.:

- (void)cancel 
{
    isNeedToExit = YES;
    [myThread release];
    myThread = nil;
}

That will cause the thread to stop and will allow your class to be deallocated (once the thread stops.) You need to ensure that all users of your class know that "cancel" needs to be called before the class is released. E.g.:

[myObject cancel]; // Stop the thread 
[myObject release];
myObject = nil;

A more traditional solution would be to simply subclass NSThread.

Upvotes: 1

Related Questions