views:

51

answers:

4

What is the best way to write a thread safe method?

I have the following method, sometimes i want to call it asynchronously (call it through a thread) And sometimes i want to call it directly on the main thread. Is there a problem with keeping the pool (alloc, release) even if I am not calling the method on a separate thread?

- (void)doStuff
{
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
     //do some stuff here?
     [pool release];
}
+1  A: 

No, there is no problem with always using your own, method-local pool. You should be using [pool drain] instead of [pool release], though.

Jeremy W. Sherman
To clarify, `[pool drain]` and `[pool release]` are identical under manual memory management, but under GC, the former triggers a collection and the latter is a no-op.
Kevin Ballard
Correct, but I see no reason not to always prefer `-drain` to `-release` for all development targeting 10.4 or later.
Jeremy W. Sherman
+2  A: 

That's perfectly safe to call on the main thread. NSAutoreleasePool maintains a stack, so in this case you're just putting a new pool on top of the stack, then popping it off when you're done.

Kevin Ballard
A: 

Regardless of what it would mean for the release pool, I would not recommend writing it this way. If you absolutely have to be able to call the method from the main and from other threads, code it like this:

- (void) doSomething {
}

- (void) doSomethingInBackground {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    [self doSomething];
    [pool release]
}

This way you wrap the method in a method that takes care of the release pool.

Ivo Jansch
A: 

I will also prefer the method mentioned by Ivo Jansch. Creating/draining a pool is valid but it may be a bit headache when you call the method doStuff: recursively or many times. But by following Ivo's method you can do stuff without a memory headache. And also for a method to be thread safe you must use locks or @synchronized() whenever its needed, usually when accessing a array/buffer/dictionary. Your method should be something like this

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

 @synchronized(lock) 
 {
    NSLog(@"Hello World");
 }
 [pool release];}
Kiran