Regarding multiple threads on the iPhone - iphone

I have a question. My case study is that I have two big SQLite databases and I want to use threads (meaning 2 processes simultaneously). Did it work well? I have written the following code:
NSAutoreleasePool *dbPool;
dbPool = [[NSAutoreleasePool alloc] init];
/* All Database work is performed here */
[dbPool release];
Please guide me. Am I doing this correctly or not? Should I use a pool to drain or release?
And in that way is this using concurrent processes, meaning it's also the same behavior as multitasking?
Thanks in advance!

Yep, you're doing it right. Each of your new thread needs own autorelease pool.
Regarding to your question about release / drain of pool, recommended is drain message.
What do you mean by sqlite database? How do you access it? If you access it via CoreData, you have keep following in your memory:
you need one NSManagedObjectContext per thread,
do not pass NSManagedObjects to another thread, just pass object ID,
before you pass object ID to another thread, save it in thread where it was modified / created before passing it.
There are more rules, but these are basic ones.
Multitasking means that you can run more applications in one time. Multithreading (= your case) means that your application does use more threads to achieve its task.

A common approach for user interface or other heavy object management work is to surround your code like you're doing, but you should be using drain:
NSAutoreleasePool *dbPool = [[NSAutoreleasePool alloc] init];
// do your work
[dbPool drain];
A lot of detail on NSAutoreleasePool is available here and a previous Stack Overflow answer here. Basically the work you're doing inside the pool, if set to autorelease, will be released once the pool drains. This can increase performance when working with certain classes that produce autoreleased instances. If you want full and immediate control though, you can release each object you're working with once it's no longer needed and ditch the pool altogether.
As to your multithreading questions I'm not sure if I understand what you're asking but nonetheless using the pool is a solid approach even in a background thread. This is assuming that the objects you're working with in the thread aren't somehow also used in another (since you might have an accidental release).

Related

Autoreleasepool for separate threads in iOS [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Does every thread need its own autorelease pool?
I would like to know why it is required to use autorelease pool, when we call some methods on a separate thread rather than the main thread, please clarify.
If you're using garbage collection EXCLUSIVELY in the thread you don't need an autorelease pool for it.
However, if you're manually managing retain counts (managed memory model) at all, even if you're using it with garbage collection as well, then each thread DOES need it's own autorelease pool.
Autorelease pools are thread-specific, that is a pool from thread A can't access/manage a pool from thread B. Typically each thread will have multiple autorelease pools to lessen memory usage. Again, nested pools are specific to their thread - they can't manage memory from other threads.
You should read up on the the iOS threading guide at https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/
Also, Apple is recommending migrating away from threading and managing concurrency with Grand Central Dispatch. It's a fair bit easier to do, IME, for anything complicated:
https://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/doc/uid/TP40008091-CH105-SW1
I think I don't get your question. Anyway you could google it what it does or for what its needed or read a book on ios development ;)
The autoreleasepool handles all your memory issues, when you are using ARC (Automatic Reference Counting). So you dont need a void dealloc method to do it and release everything at the hand manually.
This goes for main, as for seperates thread inside your app. The autoreleasepool takes care of all of them.
Hope that answers your question. Short, but simple.

NSOperationQueue, memory and GCD; how to implement properly?

I have some simple doubts about NSOperation and GCD that I have not found answer to on the documentation.
The firs question is related to memory management:
I want to know if I need to create an Autorealease pool for the methods I wil add to the NSOperationQueue; similarly to when you run a method on different thread without NSOperations.
The next question is whether NSOperation takes care of GCD or if this needs to be done manually?
Thank you for your help!
I just saw your question here and there is a post on the apple dev forums you might be interested in. According to one of the apple guys on this thread so long as you run your NSOperation through an NSOperationQueue you do not need to create your own autorelease pool as the NSOperationQueue does it for you.
Also the docs for NSOperationQueue apparently need to be updated/corrected. On devices running iOS 4 or later NSOperationQueue does use GCD despite what the class reference documents say.
According to the documentation, you should create an NSAutoreleasePool in the main method of your NSOperation. The documentation for NSInvocationOperation and NSBlockOperation doesn't specify whether they create an autorelease pool for you, so to be safe it would be best to create one when using those classes too.
The NSOperationQueue handles queuing and executing the operations, so you shouldn't have to mess with GCD yourself for tasks related to the operation queue.

Is there GC in latest iphone OS?

If we use NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; then what method is used, either drain or release for lates iOS.
no garbage collection on iOS.
I do what apple suggests in the documentation:
In a garbage-collected environment,
release is a no-op, so unless you do
not want to give the collector a hint
it is important to use drain in any
code that may be compiled for a
garbage-collected environment.
On iOS NSAutoreleasePool will drain when it goes out of the scope where it is defined (as long as no other reference is held). During the drain, it will release all objects held by it.
Thus, calling release might result in a drain, as long as it's the last reference to the pool.
This is different from the traditional GC where the collector is not scope bound and in general works independently of the main app code flow.

iPhone multi-threaded AddressBook manipulation

I have been using the AddressBook api of the iPhone for some time now. But doing some refactoring to improve application performance I have decided to "reuse" the ABAddressBookRef returned by AddressBookCreate because I noticed there are large performance improvements doing that. However, I am getting EXEC_BAD_ACCESS errors now randomly, and I think the reason is in this "caveat" in the iPhone reference implementation: http://developer.apple.com/iphone/library/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/300-BasicObjects/BasicObjects.html#//apple_ref/doc/uid/TP40007744-CH3-SW1
Important: Instances of ABAddressBookRef cannot be used by multiple threads. Each thread must make its own instance by calling ABAddressBookCreate.
Now, I thought that simply meant it was not thread-safe so I had to synchronise access to the API, but maybe I am wrong, and there is some other reasons multiple threads mess up the data structure?
Can someone confirm if it is indeed a thread-safe issue (so #synchronize should work) or some other issue?
Cheers
This is not a thread safety issue... there is no way for you to solve it with locks. The comment makes it pretty clear:
Important: Instances of ABAddressBookRef cannot be used by
multiple threads. Each thread must
make its own instance by calling
ABAddressBookCreate.
What you can do is create a single instance of the ABAddressBook and create a producer/consumer architecture that would manage the access to the object.
The wrapper will have a main thread which does one thing only: reads operation requests from a blocking queue, then performs the operations on the address book. All your threads will queue their operations to the single queue and the wrapper will execute those actions; if there is nothing in the queue then the wrapper will block until there is something in the queue.
This should solve the problem of not being allowed to use the ABAddressBookRef from multiple threads.

Why is autorelease especially dangerous/expensive for iPhone applications?

I'm looking for a primary source (or a really good explanation) to back up the claim that the use of autorelease is dangerous or overly expensive when writing software for the iPhone.
Several developers make this claim, and I have even heard that Apple does not recommend it, but I have not been able to turn up any concrete sources to back it up.
SO references:
autorelease-iphone
Why does this create a memory leak (iPhone)?
Note: I can see, from a conceptual point of view, that autorelease is slightly more expensive than a simple call to release, but I don't think that small penalty is enough to make Apple recommend against it.
What's the real story?
(cannot accept your own answer?)
Well, after all that, I did manage to find a reference from Apple Developer, added as a side-note near the bottom of the page:
iPhone OS Note: Because on iPhone OS
an application executes in a more
memory-constrained environment, the
use of autorelease pools is
discouraged in methods or blocks of
code (for example, loops) where an
application creates many objects.
Instead, you should explicitly release
objects whenever possible.
Still, this suggests using autorelease carefully, not avoiding it altogether.
(and now for my comment)
It sounds like there is a certain amount of overhead in maintaining the pool. I read this article which would lead me to probably avoid autorelease as much as possible because I prefer things to be consistent. If you have some memory under autorelease and other memory being totally manually managed it can be a bit more confusing.
It is not the question to use or not to use autorelease, because in some cases autorelease is the only way you'll get through. The question should be "Why not to use autorelease on all objects, instead of using retain and release?".
To answer that, you should first learn what's a proper use for autorelease. Let's say that you have a class that has two properties: firstName and lastName. There is a getter and a setter for each. But you also need a method that would return fullName, by concatenating these two strings into a brand new string:
- (NSString *) fullName {
NSString str = [[NSString alloc]initWithFormat:#"%# %#", firstName, lastName];
// this is not good until we put [str autorelease];
return str;
}
What's wrong with that picture? The reference count on the returned string is 1, so if you don't want to leak, the caller should release it when he's done. From the caller's point of view, he just requested a property value fullName. He is unaware of the fact that he got a brand new object that he should release after usage, and not some reference to an NSString internally held by the class!
If we put the [str release] before return, the string would be destroyed and the method would return garbage! That's where we use [str autorelease], to mark the object for release at a later time (typically when the event processing is done). That way the caller gets his object, and does not have to worry whether he should release it or not.
The convention is to call autorelease on a new object before the method returns it to the caller. Exceptions are methods with names that start with alloc, new or copy. In such cases the callers know that a brand new object is created for them and it is their duty to call release on that object.
Replacing release with autorelease altogether is a bad idea, since the objects would pile up and clog the memory very quickly, especially in loops. The resources on the iPhone are limited, so in order to minimize memory hogging, it is your duty to release the object as soon as you're done with it.
I disagree that avoiding autorelease altogether is wise.
Cocoa Touch uses it quite frequently internally and for many situations it's the only way to allocate memory properly (a good example is reusable table view cells). If you understand what is happening, the autorelease pool is a great tool at your disposal. The main thing to remember is that the blocks are not freed until some point later in the run loop. If you are running a tight loop without user interaction and are piling up autorelease blocks, you will eventually run out of memory.
Autorelease is not a substitute for garbage collection (not available on in the iPhone SDK) and can lead to nasty dangling pointer bugs (the pointer still seems to be good, then at some unpredictable point goes invalid), but is also very useful in writing clear and easy to maintain code. Consider the following case:
[aDictionary writeToFile:
[documentsDirectory stringByAppendingPathComponent:#"settings.plist"]
atomically:YES];
The path string is generated as an autorelease object. We aren't required to create a temporary object, so we avoid that overhead (and the possibility we might forget to release it). The memory will be fully released (no leaks), just that it will happen later in the run loop. Ask yourself: am I going to allocate hundreds of these before I get back to user input? If no (as would be the case here), autorelease is a great solution and indeed this NSString method for working with paths is only available using autoreleased memory.
I do agree with the above poster that following convention and being consistent is a very good idea.
I tend to avoid using autorelease on the iPhone where I can (as Jon points out, you can't always do without it), simply because I like to know that the objects I'm working with are released the instant I don't need them. Memory constraints are one of the largest problems you'll face on the device and I believe they're the source of most of the crashing issues you'll find out there.
As highlighted by Apple, a particular area of concern is when you use autoreleased objects within any kind of loop, because they'll pile up within the autorelease pool. You then have to manage when to drain the pool or create / release one. Doing that every pass through the loop might degrade performance, but going too many passes without could lead to dangerous memory usage. I'm still tweaking this in Molecules, because there are intermittent memory issues when importing large (>2 MB) text files from the Protein Data Bank. I was able to improve performance by minimizing autoreleased objects, but couldn't eliminate them completely.
Another area to watch out for is using autoreleased objects with threads. If at all possible, do not use autoreleased objects when dealing with methods performed on a background thread, because the pool can be drained at random times. This leads to intermittent crashes that can be really fun to track down.
I would highly suggest avoiding autorelease like the plague. Memory management bugs are a great way to waste massive amounts of time and money, I've had the dubious honor of going through the process many a time on old Mac apps, and the fact that the iPhone has tight memory constraints mean that you have to be extremely careful, or the app will just be unstable and crash often...like so many of the first apps that were released last summer.
The only reliable way I've found to write stable iPhone applications is to manage all your memory yourself, and do it consistently. Even if you are the only programmer on your project, you'll thank yourself later. It can be difficult if you learned to program in languages that "take care of everything for you," but it really is worth learning how to do well if you are serious about createing quality iPhone apps.