I have a custom model class with an NSMutableData ivar that will be accessed by custom NSOperation subclasses (using an NSOperationQueue). I think I can guarantee thread-safe access to the ivar from multiple NSOperations by using dependencies, and I can guarantee that I don't access the ivar from other code (say my main app thread) by waiting until the Q has finished all operations.
Should I use a nonatomic property specification, or leave it atomic? Is there a significant impact on performance?
Andrew, whether it's significant depends on what you are doing. If your Operations are uploading movies to youtube and each operation needs to read the data once then it doesn't make the slightest bit of difference - just leave it as atomic.
Otherwise you need to profile to see if it is significant. If you are sure (you don't sound that sure) that the NSMutableData will never be accessed from two or more threads simultaneously (however you do it, lock, barriers, or just waiting) then you don't have a need for it to be atomic.
Premature optimisation is the root of all evil.
Leave it atomic until you find out for sure that there is a performance issue.
If it's a mutable object then your biggest enemy is concurrent mutation, not inconsistent property access.
Related
While using theinversifyJS library, I saw a statement that the singleton pattern is safe because node.js is single-threaded.
How does single-threading benefit from singletons over multithreading?
It's hard to know what the author meant. One likely explanation is that a single thread can't race with itself when lazily initializing a singleton. In a multi-threaded environment, two threads could naively test whether the singleton has been initialized, then both could initialize it, meaning it's no longer truly a singleton. This could cause problems if initializing it has side effects.
I am still getting used to some of the details of memory management in objective-c, despite the fact that ARC simplifies things significantly. Here is a line of code:
[song addEntriesObject:self.entry];
where song is a managed object that I access by executing a fetch request on my managed object context, and self.entry refers to an instance variable that is passed into this class upon initialization, and is also a managed object (i.e. it's a core data entity - hope I'm using that terminology properly).
My question is simply whether this will cause any problems in memory management, i.e. whether assigning self.entry to a managed object will prevent that instance variable from being released because it is being retained by core data, or something along those lines. Would this create any problems, or does core data not maintain pointers to objects in the same way? Or am I just completely on the wrong track with my thought process here?
Any thoughts on the subject would be much appreciated.
cowfaboo,
Core Data objects are NSObjects and hence behave identically. In other words, nothing changes with respect to memory management. In your example, self.entry is retained by both your instance and by song.
Independent of ARC, Core Data items can retain large object graphs. These may need to be pruned. The -refreshObject:mergeChanges: method is used to do this. To save yourself some pain, you should always use -save: before trimming your graph.
Andrew
Can anybody give me example that NSMutableArray is thread safe or not?
It is not thread safe. See the list of thread safe/unsafe classes here
According to the Apple docs NSMutableArray is not thread safe.
Mutable objects are generally not
thread-safe. To use mutable objects in
a threaded application, the
application must synchronize access to
them using locks. (For more
information, see “Atomic Operations”).
In general, the collection classes
(for example, NSMutableArray,
NSMutableDictionary) are not
thread-safe when mutations are
concerned. That is, if one or more
threads are changing the same array,
problems can occur. You must lock
around spots where reads and writes
occur to assure thread safety.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html
Does it turn some managed objects into faults when there's a Low Memory Warning? Or must we do that manually by calling the -refreshObjects:mergeChanges: method which puts the affected managed objects on diet quickly? And...would that actually hurt? What if these objects are currently used by an NSFetchedResultsController to show up on a table view?
Yes, Core Data listens for low memory warnings and will drop its cache and attempt to fault any object that it can to reduce its memory consumption.
If the object is currently being used it would automatically realize that object the next time you accessed on of its properties so from your application's point of view, nothing has happened and no NSManagedObject entities have been released.
In the case where you have established a relationship between two objects, you MUST use the managedObjectContext method -refreshObject:mergeChanges:NO after doing a save, to tell CoreData that the related object can be released. I think of it as the moral equivalent to a [object release]; statement; you are telling CoreData to release the object it read it from the DB. The tradeoff, as Marcus says, is that it will be released from memory cache, but have to be read back in by core data. the good news is that it happens behind the scenes and you don't have to program for it; the bad news is that it happens behind the scenes and thus can 'magically' chew up memory.
Ways around it are many; for example, use a predicate to only select the rows you absolutely must need; don't do a general call to fetch everything and then go through the list one by one. More than likely you will crash when you do the general call and CoreData attempts to load all objects.
The docs say that I should not release any modeled property in -dealloc. For me, that feels like violating the big memory management rules. I see a big retain in the header and no -release, because Core Data seems to do it at any other time.
Is it because Core Data may drop the value of a property dynamically, at any time when needed? And what's Core Data doing when dropping an managed object? If there's no -dealloc, then how and when are the properties getting freed up?
Core Data has NSManagedObjects as their base object, they are managed by the system and you do not have to do any memory managment on them...well unless u declare your own properties in a class that are not defined in the object model...
The tricky bit of managed object memory comes when the objects are turned into faults. A fault is a ghost of the object. It exists and responds to messages but it doesn't have it's attributes populated. For example, you can count the number of objects in a to-many relationship even if the objects themselves are faults.
Faults are used to maintain the object graph in memory without the overhead of the actual data. The object is still technically alive so its dealloc has never been called.
When the context turns an object into a fault, the object releases and nils it's attributes in memory. It does this in willTurnIntoFault and didTurnIntoFault. If you need to do some special releasing you should override those methods (usually the latter.)
Faulting makes managed objects rely on different methods than other classes for intialization and clean up. You intialize in awakeFromInsert or awakeFromFetch and you dealloc in willTurnIntoFault and didTurnIntoFault.
It's important to follow the rules for managed objects because the context might keep thousands of faulted objects in memory. If you create a custom attribute but do not release it when the object becomes a fault, then you could easily tie up a large amount of memory accidentally.