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];
}
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.
No, there is no problem with always using your own, method-local pool. You should be using [pool drain] instead of [pool release], though.
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.
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];}
Related
Based on Bavarious's answer to this SO question, I am led to believe that #autoreleasepool is now an Objective-C language feature if you build with LLVM/clang.
This being the case, how does one rewrite the following code to use an #autoreleasepool instead of an NSAutoreleasePool in a non-ARC environment?
[NSAutoreleasePool addObject:anObject]; // (*)
Background: I essentially want to write a custom implementation of -autorelease that does not in any way interact with the NSAutoreleasePool class:
#autoreleasepool {
SomeCls *obj = [[SomeCls alloc] init];
[obj autorelease]; // Does not go through an NSAutoreleasePool object
// ...
}
#autoreleasepool { } is a new language feature meant to obviate the need to drain the current pool at every exit point of a function. Now, instead of having to write:
void f(void) {
//Make a new pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//Every inner scope that exits prematurely requires a drain
if (life_is_good) {
for (int i = 0; i < 1000; i++) {
NSObject *obj = [[[NSObject alloc]init]autorelease];
//breaks out of the loop, and the function, so drain the pool
if (life_is_bad) {
[pool drain];
return;
}
}
//Life gets bad below here, so return
[pool drain];
return;
}
//end of function requires drain.
[pool drain];
}
You can wrap the entire function in an #autoreleasepool { } directive and the compiler will insert the proper drains where the function returns:
void f(void) {
//Make a new pool
#autoreleasepool {
if (life_is_good) {
for (int i = 0; i < 1000; i++) {
NSObject *obj = [[[NSObject alloc]init]autorelease];
//breaks out of the loop, and the function, so drain the pool
if (life_is_bad) {
//[pool drain]; auto-drain
return;
}
}
//[pool drain]; auto-drain
return;
}
//[pool drain]; auto-drain
}
}
I have no idea why you would want to forgo the automatic pool mechanism, as it handles a huge amount of work for you (page management, per-thread pool management, releasing objects in a timely yet efficient manner), but it shouldn't be that much of a hassle to get a primitive NSAutoreleasePool up and running. Any autoreleasepool would require a page manager (malloc() and realloc()), pointer storage (a simple array), and some way to detect whether or not the current scope in which it is being used has exited (-drain). A simple pool could just be a thread-safe singleton, but be wary of how many objects you try to insert and remove at one time with that implementation. You just might segfault if you try to allocate too many hot pages for too many objects.
Based on Bavarious's answer to this SO question, I am led to believe that #autoreleasepool is now an Objective-C language feature if you build with LLVM/clang.
Correct.
This being the case, how does one rewrite the following code to use an #autoreleasepool instead of an NSAutoreleasePool in a non-ARC environment?
[NSAutoreleasePool addObject:anObject]; // (*)
Doc: Normally you don’t invoke this method directly—you send autorelease to object instead.
#autoreleasepool {
id anObject = ...;
[anObject autorelease];
}
Background: I essentially want to write a custom implementation of -autorelease that does not in any way interact with the NSAutoreleasePool class:
You can't even subclass NSAutoreleasePool any longer (in a meaningful way). Unless you never pass the object to other APIs which are free to autorelease, your objects are going to end up in the current autorelease pool. The mechanics of this today is not even object based.
If this is impossible, I would be open to workaround suggestions not involving NSAutoreleasePool.
Not certain what problem you are trying to solve, but you can extend lifetimes using:
NSMutableArray * fauxAutoreleasePool = NSMutableArray.new;
id anObject = ...;
[fauxAutoreleasePool addObject:anObject];
...
[fauxAutoreleasePool removeAllObjects]; // << explicitly drain, which also happens when the array is destroyed
Of course, you could write your own implementation. Why you would write your own is still a mystery, and not a good idea for production code (#autoreleasepool works well).
Though I have already marked an answer as accepted, and offered a bounty at the time, I have since found the true answer I was searching for and realised my question wasn't very clear - primarily because I didn't know what to ask.
How to interact with #autoreleasepool:
When the compiler comes across an #autoreleasepool { } block, it automatically inserts two function calls. At the opening of the block it inserts the C function call:
void *_objc_autoreleasePoolPush(void);
At the close of the #autoreleasepool block (including when a return or break is encountered within - but NOT when an exception is thrown according to the LLVM docs) the compiler inserts the C function call:
_objc_autoreleasePoolPop(void *ctxt); // ctxt is Apple's label for the param
I believe the void *ctxt parameter is an indicator of where the current #autoreleasepool started (really only useful in Apple's implementation - see here). In any case I found it can easily be ignored in custom implementations.
The -autorelease selector:
Essentially the methodology is this:
Create (if outermost block) or mark (if inner block) an autorelease pool object (in C or C++) in _objc_autoreleasePoolPush(). It seems easiest to me to use a Stack data structure for this but YMMV.
Ensure this object is in scope within the -autorelease selector, or you have a fail-safe way of accessing it.
Add the object to the autorelease pool object (in whatever way that may be) inside -autorelease.
In _objc_autoreleasePoolPop(void *), send the -release message to every item in the autorelease pool object until the marker set in _objc_autoreleasePoolPush() is reached (or you reach the bottom of the pool). Then do any additional required cleanup.
Final notes on threading:
Objective-C #autoreleasepools are supposed to be thread-local. That is, each thread has its own (if it requires one). As a result, _objc_autoreleasePoolPush() must have some way of determining whether the current thread already has an active autorelease pool and create the object if it does not.
Similarly, this is why, when creating a thread, the thread must first open an #autoreleasepool { } block before it does anything else (in Objective-C), and the final thing it must do is close that #autoreleasepool block (implicitly through break or return or with explicit fall-through).
Three final observations:
If you wish to implement your own autorelease pool object, you will need some form of thread-local storage to store it.
That last point about threading is why every Objective-C program must begin with an #autoreleasepool { } block in main().
This is why Apple ask you to use the NSThread class and GCD rather than DIY threading - they take care of all of this for you!
At the end of the #autoreleasepool block, the autoreleased objects are sent a release message.
If you want to reimplement the autorelease method, you may not want to directly send release messages to your NSObjectsubclass. If so, reimplementing release with some special behavior could do your business.
Background: I essentially want to write a custom implementation of
-autorelease that does not in any way interact with the NSAutoreleasePool class:
What makes you think that -autorelease interacts with NSAutoreleasePool?
As long as you are running on iOS 5+ or Mac OS X 10.7+, both the #autoreleasepool and -[NSObject autorelease] will use the runtime autorelease pool management functions, and have nothing to do with NSAutoreleasePool at all (and NSAutoreleasePool on those OS versions is simply a wrapper around the runtime functions).
I have an NSOperation where inside its -main method I use [NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:self withObject:anArgument];
aObject (instance variable of my NSOperation subclass) is a weak reference to an object of an autoreleased array returned inside the -main method...
-(void)main {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *clients = [group produceClients]; // clients array is an autorelease instance
self->aObject = [clients objectAtIndex:3]; // a weak reference, Lets say at index three!
[NSThread detachNewThreadSelector:#selector(aMethod:)
toTarget:self
withObject:#"I use this for another thing"];
// Do other things here that may take some time
[pool release];
}
-(void)aMethod:(NSString*)aStr {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// aStr object is reserved for another functionality
// I know that I could pass a NSDictionary with a number of entries, which would be
// retained by `detachNewThreadSelector` but then ...
// I wouldn't have to ask this question ! :)
// Do several things with aObject, which is a weak reference as described above.
NSLog(#"%#", [self->aObject.id]);
// Is it safe ?
[pool release];
}
I know that NSThread's detachNewThreadSelector method retains self and withObject:anArgument, but what happens to aObject ?? Is it sure that will exist during the execution of the detached thread (aMethod:) ? Self is retained by detachNewThreadSelector, does this mean that the pool of the -main thread will be delayed released since it is retained and thus the clients will exist and thus the aObject will exist ?
Or the -main (NSOperation) thread will finish execution and released before -aMethod (NSThread) finishes so it's unsafe to use aObject there ?
The real question is: When calling [NSThread detachNewThreadSelector:#selector(aMethod:) ...toTarget:self ...] from inside a thread, does the last thread being retained in a way that its autoreleased instances (clients array) are safe to be used in aMethod (self->aObject) (lets say via weak references) ?
Your approach seems highly unstable, but I'm not an expert on multithreading so I could be wrong. Your clients array is in the main autorelease pool, which you cannot be assured will wait till your aMethod thread is completed to drain. What about this:
-(void)main {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSThread detachNewThreadSelector:#selector(aMethod:)
toTarget:self
withObject:#"I use this for another thing"];
[pool release];
}
-(void)aMethod:(NSString*)aStr {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *clients = [group produceClients]; // clients array is an autorelease instance
self->aObject = [clients objectAtIndex:3]; // a weak reference, Lets say at index three!
[pool release];
}
With this approach, your clients array is in the thread's autorelease pool.
I found an example of Objective-C/cocoa framework has the following code.
int main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Create an array
NSArray *month = [NSArray arrayWithObjects:# ... nill];
[pool drain];
}
Q1 : What's the magic behind this (Why do I need to have the NSAutoreleasePool code?)? What magic is happening between the NSAutoreleasePool and pool drain block? I see I don't need to release*month myself. Is this because it's inside the NSAutoreleasePool and pool drain block?
Q2 : With Xcode, I'm already given the main() function. In this case, how can I use the NSAutoreleasePool and pool drain?
For example :
int main(int argc, char *argv[])
{
//NSAutoreleasePool *pool = [[[NSAutoreleasePool] alloc] init];
return NSApplicationMain(argc, (const char **) argv);
}
Q1: The magic is that NSObject -autorelease instance method calls NSAutoreleasePool +addObject: class method. The NSObject instance is pooled in the current NSAutoreleasePool instance. And NSAutoreleasePool -drain instance method calls release method of pooled instances.
It is not the exactly same between Cocoa implementation of Apple and GNUstep, but it is similar.
NSObject.m
NSAutoreleasePool.m
I'm not sure why month is not released, it should be release by drain.
Q2: You can use NSAutoreleasePool wherever you want to use at. Instantiate a NSAutoreleasePool means the current pool will be changed by the new instance. drain will go back the current pool to the previous instance.
Besides NSApplicationMain never returns. It calls the exit function to exit the application and terminate the process.
Q1:
You don't need to release the month instance in the example you give because the NSArray class method you're calling (arrayWithObjects:) returns an instance that is autoreleased. By convention in Cocoa, class methods that start with the name of the class will return autoreleased instances of that class. These examples:
[NSString stringWithFormat:#"Holla %#", #"back girl!", nil];
[NSArray arrayWithObjects:#"Holla", #"back", #"girl!", nil];
Will both return instances of their respective objects that are autoreleased.
I'm fairly new to Objective C, but let me give this a crack:
The autorelease pool is a way for Objective C to handle garbage collection in a somewhat easier way than manually.
It does this by counting references, or in this case every time you call "retain" or "release".
So if you have an instance of an object in "a", you could do:
This puts it into the AutoreleasePool:
[a autorelease];
This tells the autorelease pool that you want to hold on to it for a while:
[a retain];
When you call [pool drain] now, it will notice that you have one reference to a, and it won't deallocate the memory. However, if you later call [a release], the next time [pool drain] is called, it'll see that there are no further references to a remaining, and deallocate the memory.
I have a sneaking suspicion that I just talked myself in circles without making a whole lot of sense, but here is the wikipedia article on reference counting: http://en.wikipedia.org/wiki/Reference_counting
As I'm mastering my skills with multithreading with GCD, I've come across some question. Suppose you have the following method:
- (void)method {
NSString *string= [NSString string]; //will be autoreleased
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//very very lengthy operation...
NSLog(#"%#", string); //is it safe?
});
}
I'm wondering if this is correct, because I think I should have retained string before the block execution: in fact I fear that the event loop finishes and sends string an autorelease message before using string in the block. That would crash the program.
Am I right? Should I send a retain and a release message to string or this is the correct implementation?
Thanks in advance!
I'm wondering if this is correct, because I think I should have retained string before the block execution: in fact I fear that the event loop finishes and sends string an autorelease message before using string in the block.
Fear not:
A block captures the scope of the surrounding method/function in that it automatically retains any object-variable that is used inside of the block. Be aware of that when you use self inside of a block, as this may greatly affect the lifetime of the object!
There is one exception to this rule, and that are variables declared as
__block SomeObjectPointerType variableName
Update
Because there’s a new comment on this answer, I should probably add that things changed a little with the introduction of ARC:
Under ARC all object variables default to __strong, and this holds for variables marked with __block as well. If you want to avoid strong capturing of a variable in a block, you should define a local variable that is __weak.
End Update
If you like to learn more about blocks, bbum gave an excellent session called Introducing Blocks and Grand Central Dispatch on iPhone at WWDC 2010.
The "Block Details" section starts at 11:30.
The concern is; when an autorelease object releases?
NSString *myString= [NSString stringWithFormat: #"%#", stringVariable];
The myString depends upon stringVariable, whenever stringVariable releases the myString immediately releases.
NSString *myString= [NSString stringWithString: #"stringVariable"];
In practice it is observed the myString might be releases just after the completion of the method.
Now if you change your code and use NSAutoReleasePool
- (void)method {
NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];
NSString *string= [NSString string]; //will be autoreleased
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//very very lengthy operation...
// string will be released here
[pool release];
NSLog(#"%#", string); // it is not safe?
});
}
The autorelease objects released when the auto release pool releases in which they exists or when the object releases on which they depends.
Now if you are using the method in a thread you should use auto release pool inside it.
- (void)method {
NSAutoreleasePool pool = [[NSAutoreleasePool alloc] init];
// lengthy operations ...
[pool release];
}
I am new in objective-c and I am trying to understand memory management to get it right.
After reading the excellent
Memory Management Programming Guide for Cocoa by apple my only concern is when
actually an autoreleased object is released in an iphone/ipod application. My understanding is at the end of a run loop. But what defines a run loop in the application?
So I was wondering whether the following piece of code is right. Assume an object
#implementation Test
- (NSString *) functionA {
NSString *stringA;
stringA = [[[NSString alloc] initWithString:#"Hello"] autorelease]
return stringA;
}
- (NSString *) functionB {
NSString *stringB;
stringB = [self functionA];
return stringB;
}
- (NSString *) functionC {
NSString *stringC;
stringC = [self functionB];
return stringC;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSString* p = [self functionC];
NSLog(#"string is %#",p);
}
#end
Is this code valid?
From the apple text I understand that the NSString returned from functionA is valid in the scope of functionB. I am not sure whether it is valid in functionC and in viewDidLoad.
Thanks!
Yes, your functions are valid, and return objects using correct Cocoa conventions for retain/release/autorelease/copy.
To answer your question about what the runloop is, in your application's main() function, it invokes UIApplicationMain(). You can imagine UIApplicationMain looks something like this:
void int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName) {
UIApplication *app = /* create app using principalClassName */;
[app setDelegate:/* create delegate using delegateClassName */];
while (![app shouldTerminate]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
event = [app getNextEvent];
[app dispatchEvent:event];
[pool drain];
}
}
That while loops is similar to what the UIKit is actually doing, and each trip through that while loop is like a trip through the runloop, where the function getNextEvent blocks waiting for some event to happen. All of your methods are typically called from within something like dispatchEvent:. You might try setting a break point in one of your methods, like an IBAction, and looking in the debugger call stack way up at the top to see the names of the UIKit methods that handle the events and runloop. Since each of your methods are called from within that while loop, each time you call autorelease on an object, that object is added to that outter pool in the run loop. When the current event is finished being dispatched, the pool is drained, and those objects are finally sent release messages.
One last note. There can be more than one autorelease pool, that aren't always at the end of the event loop. Sometimes you might allocate tens of thousands of objects in one trip thorough the event loop. When that happens, you might setup additional inner auto release pools in your own methods to keep the number of autoreleased objects in autorelease pools down. Auto release pools can stack.
There's nothing wrong with that code. It will compile and run as you expect.
The NSString object returned from functionA is still valid upon return since it's being passed down the stack to the next guy (functionB) who is now keeping track of it.