Can I snapshot and restore memory of Objective-C object graph? - objective-c

I'm designing a object persistent code.
IMO, memory snapshot is fastest, reliable and compact persistent method within a few limitation.
It's easy with C structs. I can layout all objects' memory layout manually. I can save all references as index of object collection. So reference is not a problem.
Anyway I want to try this with Objective-C objects. To do this, objects must be positioned in specific location of memory. So, if I can specify memory location of allocation, I can snapshot the memory. And when restoring, I can get an object at specific address.
Of course, all of these are machine-specific and needs many tricks, but it's fine to me.
The only problem is I don't know way to specify location of new Objective-C object. How can I do this?

Generally people use NSCoding and NSKeyedArchiver (or some custom subclass thereof). I think your C method would have worked before the 64-bit runtime, since the data part of objects was implemented using structs, but I think the new runtime's use of nonfragile instance variables would complicate matters. In any event, the program that loads the persistent objects still has to have the class definitions for them, either hard-coded or loaded via bundles.

Related

Cocoa Deep Copy Containers

I am tying to understand the example in the apple docs for deep copying an array of dictionaries Here.
In Listing 3 A true deep copy
The example shows
NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];
Notice there is no copy, mutable copy , or autorelease operators, so I am struggling to understand how this is a copy and how it gets released. In fact, if I release my implementation, it will crash. It does however work as expected, and there does not appear to be any abandoned memory using it as the example shows.
I looked the the NSUnarchiver class reference and it mentions that the unarchiveObjectWithData method creates a temporary copy of the object(s)?
Does this mean the proper implementation then is to allocate and init the new array rather than just assigning the pointer so it can be released?
Thanks in advance.
They are doing a deep copy by doing a full archival pass on the object graph. Using NSArchiver enables things like automatic cyclic reference management and the objects can choose not to encode things like their delegate or they can hook stuff back up on unarchival.
For all intents and purposes, it is archival by saving something to disk and then reading it back in as a new document. Only, instead of the disk, it is just stored in memory all the time.
It is slow, very expensive, and totally inappropriate for anything but when you very occasionally need to duplicate a complex object graph completely.
unarchiveObjectWithData: returns an auto-released object. If you using MRC, you need to retain it if you want to keep it. But, a better solution would be to move to ARC.
You are crashing on retain (or shortly after) because you did not respect Apple's stated memory management rules, which can be found here: https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
Did you get the object from a method that contains alloc, new, copy or deepCopy in its name? No, then it is not your responsibility to release it.
Do you want to hold on to this object? If so, it is your responsibility to retain it.
As to why this code snippet results in a deep copy, you should read again what the archiver classes do. They don't deal with your objects, they deal with "descriptions of the contents of your objects". You might just as easily have done a "json import of the result of a json export" or an "xml import of an xml export".

Objective-c: Objects by value / Structs with methods / How can I get something like that?

I'm starting to code in objective-c and I've just realized that objects can only be passed by reference.
What if I need an object to use static memory by default and to be copied instead of referenced?
For example, I have an object Color with 3 int components r, g and b. I dont want these objects to be in dynamic memory and referenced when passing to functions, I want them immutable and to be copied like an int or a float.
I know I can use a c struct, but I also need the object Color to have methods that gets/sets lightness, hue, saturation, etc. I want my code to be object oriented.
Is there any solution to this?
EDIT: If for example I'm building a 3d game engine, where I'll have classes like Vector2, Vector3, Matrix, Ray, Color, etc: 1) I need them to be mutable. 2) The size of the objects is roughly the same size of a pointer, so why would I be copying pointers when I can copy the object? It would be simpler, more efficient, and I wouldnt need to manage memory, specially on methods that returns colors. And In the case of a game engine, efficiency is critical.
So, if there is no solution to this... Should I use c-structs and use c-function to work on them? Isn't there a better choice?
Thanks.
You can't do this. This isn't how Objective-C works (at least the Apple/GNU version*). It simply isn't designed for that sort of extreme low-level efficiency. Objects are allocated in dynamic memory and their lifetimes are controlled by methods you call on them, and that's just how it works. If you want more low-level efficiency, you can either use plain C structs or C++. But keep in mind that worrying about this is pointless in 99% of circumstances — the epitome of premature optimization. Objective-C programs are generally very competitive with C++ equivalents both in execution speed and memory use despite this minor inefficiency. I wouldn't go for a more difficult solution until profiling had proved it to be necessary.
Also, when you're new to Objective-C, it's easy to psych yourself out over memory management. In a normal Cocoa (Touch) program, you shouldn't need to bother about it too much. Return autoreleased objects from methods, use setters to assign objects you want to keep around.
*Note: There was an old implementation of Objective-C called the Portable Object Compiler that did have this ability, but it's unrelated to and incompatible with the Objective-C used on Macs and iOS devices. Also, the Apple Objective-C runtime includes special support for Blocks to be allocated on the stack, which is why you must copy them (copy reproduces the block in dynamic memory like a normal object) if you want to store them.
What if I need an object to use static memory by default and to be copied instead of referenced?
You don't.
Seriously. You never need an object to use static memory or be allocated on the stack. C++ allows you to do it, but no other object oriented language I know does.
For example, I have an object Color with 3 int components r, g and b. I dont want these objects to be in dynamic memory and referenced when passing to functions, I want them immutable and to be copied like an int or a float.
Why do you not want the objects to be in static memory? What advantage do you think that gives you?
On the other hand it's easy to make Objective-C objects immutable. Just make the instance variables private and don't provide any methods that can change them once the object is initialised. This is exactly how the built in immutable classes work e.g. NSArray, NSString.
One solution that people use sometimes is to use a singleton object (assuming you only need one of the objects for your entire app's lifetime). In that case, you define a class method on the class and have it return an object that it creates once when it is first requested. So you can do something like:
#implementation MyObject
+ (MyObject *)sharedObjectInstance
{
static MyObject *theObject=nil;
if (theObject==nil)
{
theObject = [[MyObject alloc] init];
}
return theObject;
}
#end
Of course the object itself isn't what's being statically allocated, it's the pointer to the object that's statically allocated, but in any case the object will stick around until the application terminates.
There are times when you want to do this because you really only want one globally shared instance of a particular object. However, if that's not your objective, I'm not sure why you'd want to do what you're describing. You can always use the -copy method to create a copy of an object (assuming the object conforms to the NSCopying protocol) to manipulate without touching the original.
EDIT: Based on your comments above it seems you just want to have immutable objects that you can copy and modify the copies. So using -copy is probably the way to go.

Objective-C Multithreading and Data Containers

I have sort of a simple question. I am writing an Objective-C program with some multithreading. I have a global NSArray, and I add objects into that NSArray from a method that is called in a new thread. If the objects I add into that NSArray are new objects created in that method (local), will that create memory access and/or other issues or will the garbage collector be smart enough to keep those objects around until they have no more references? Also, if I want to an object into that NSArray, will that object be passed by reference or by value?
Can you add objects in NSArray? I guess you mean NSMutableArray.
NSMutableArray is NOT thread safe. So you may need to acquire a lock before trying to modify it. Though this will mostly dependent on how your threads are working on shared data.
NSArray or NSMutableArray will retain the objects that they contains. So after adding you can release the local copy.
The array will store the reference.
Hope it helps. In general multithreading is much more difficult than a single thread app. Please check Threading Programming Guide for the details. It may save you from many hazards.
There should be no problems with the design you're describing. All of your threads share the same memory space, so everything will work just fine. The memory management system will do "the right thing", but I recommend learning the retain/release method - there's nothing better than actually understanding what your program is doing.
Objective-C is pass-by-value only, just like C. That said, objects are only ever passed around by pointers in Objective-C, so you can think of it as always pass-by-reference in that sense.

Instance caching in Objective C

I want to cache the instances of a certain class. The class keeps a dictionary of all its instances and when somebody requests a new instance, the class tries to satisfy the request from the cache first. There is a small problem with memory management though: The dictionary cache retains the inserted objects, so that they never get deallocated. I do want them to get deallocated, so that I had to overload the release method and when the retain count drops to one, I can remove the instance from cache and let it get deallocated.
This works, but I am not comfortable mucking around the release method and find the solution overly complicated. I thought I could use some hashing class that does not retain the objects it stores. Is there such? The idea is that when the last user of a certain instance releases it, the instance would automatically disappear from the cache.
NSHashTable seems to be what I am looking for, but the documentation talks about “supporting weak relationships in a garbage-collected environment.” Does it also work without garbage collection?
Clarification: I cannot afford to keep the instances in memory unless somebody really needs them, that is why I want to purge the instance from the cache when the last “real” user releases it.
Better solution: This was on the iPhone, I wanted to cache some textures and on the other hand I wanted to free them from memory as soon as the last real holder released them. The easier way to code this is through another class (let’s call it TextureManager). This class manages the texture instances and caches them, so that subsequent calls for texture with the same name are served from the cache. There is no need to purge the cache immediately as the last user releases the texture. We can simply keep the texture cached in memory and when the device gets short on memory, we receive the low memory warning and can purge the cache. This is a better solution, because the caching stuff does not pollute the Texture class, we do not have to mess with release and there is even a higher chance for cache hits. The TextureManager can be abstracted into a ResourceManager, so that it can cache other data, not only textures.
Yes, you can use an NSHashTable to build what is essentially a non-retaining dictionary. Alternatively, you can call CFDictionaryCreate with NULL for release and retain callbacks. You can then simply typecast the result to a NSDictionary thanks to tollfree bridging, and use it just like a normal NSDictionary except for not fiddling with retain counts.
If you do this the dictionary will not automatically zero the reference, you will need to make sure to remove it when you dealloc an instance.
What you want is a zeroing weak reference (it's not a "Graal of cache managing algorithms", it's a well known pattern). The problem is that Objective C provides you with zeroing weak references only when running with garbage collection, not in manual memory managed programs. And the iPhone does not provide garbage collection (yet).
All the answers so far seem to point you to half-solutions.
Using a non-reataining reference is not sufficient because you will need to zero it out (or remove the entry from the dictionary) when the referenced object is deallocated. However this must be done BEFORE the -dealloc method of that object is called otherwise the very existence of the cache expose you to the risk that the object is resurrected. The way to do this is to dynamically subclass the object when you create the weak reference and, in the dynamically created subclass, override -release to use a lock and -dealloc to zero out the weak reference(s).
This works in general but it fails miserably for toll-free bridged Core Foundation objects. Unfortunately the only solution, if you need to to extend the technique to toll-free bridged objects, requires some hacking and undocumented stuff (see here for code and explanations) and is therefore not usable for iOS or programs that you want to sell on the Mac App Store.
If you need to sell on the Apple stores and must therefore avoid undocumented stuff, your best alternative is to implement locked access to a retaining cache and then scavenge it for references with a current -retainCount value of 1 when you want to release memory. As long as all accesses to the cache are done with the lock held, if you observe a count of 1 while holding the lock you know that there's no-one that can resurrect the object if you remove it from the cache (and therefore release it) before relinquishing the lock.
For iOS you can use UIApplicationDidReceiveMemoryWarningNotification to trigger the scavenging. On the mac you need to implement your own logic: maybe just a periodical check or even simply a periodical scavenging (both solutions would also work on iOS).
I've just implemented this kind of thing by using an NSMutableDictionary and registering for UIApplicationDidReceiveMemoryWarningNotification. On a memory warning I remove anything from the dictionary with a retainCount of 1...
Use [NSValue valueWithNonretainedObject:] to wrap the instance in an NSValue and put that in the dictionary. In the instance dealloc method, remove the corresponding entry from the dictionary. No messing with retain.
My understanding is that you want to implement the Graal of cache managing algorithms: drop items that will no longer be used.
You may want to consider other criteria, such as dropping the least recently requested items.
I think the way I would approach this is to maintain a separate count or a flag somewhere to indicate if the object in the cache is being used or not. You could then check this when you're done with an object, or just run a check every n seconds to see if it needs to be released or not.
I would avoid any solution involving releasing the object before removing it from the dictionary (using NSValue's valueWithNonretainedObject: would be another way to accomplish this). It would just cause you problems in the long run.

Self-owned objects in Objective-C Garbage Collection

I'm wondering what are the recommended ways to handle situations where, in memory managed code, object didn't belong to any particular owner, i.e. objects released themselves. One such example could be a subclass of NSWindowController, which configures, displays and manages input and output of a single window. The controller object displays a window and releases itself later at some point (usually when the window or sheet it manages is closed). AppKit provides couple examples as well: NSAnimation retains itself in startAnimation and releases itself when the animation is done. Another example is NSWindow, which can be configured to release itself when closed.
When implementing these "self-owned" objects myself, I see at least three different GC-safe patterns, but all of them have some drawbacks.
a). Using CFRetain/CFRelease.
Self-owned object calls CFRetain on self before it starts its operation (e.g. in the window controller example before the window is displayed). It then calls CFRelease() on self when it's done (e.g. in the window controller example after the window is closed).
Pros: User of the object doesn't have to worry about memory management.
Cons: A bit ugly, since requires use of memory management functions, although we're using GC in pure ObjC code. If CFRelease() isn't called, leak may be hard to locate.
b). Avoiding self-ownership idiom with static data structure.
Object adds itself into a data structure (e.g. a static mutable array) before it starts its operation and removes itself from there when it's done.
Pros: User of the object doesn't have to worry about memory management. No calls to memory management functions. Objects have explicit owner. Potential leaks are easy to locate.
Cons: Locking is needed if objects may be created from different threads. Extra data structure.
c). Avoiding self-ownership idiom by requiring the user of object to save a reference to the object (e.g. into an ivar).
Pros: No calls to memory management functions. Objects have explicit owner.
Cons: User of the object has to keep a reference even if it doesn't need the object anymore. Extra ivars.
What pattern would you use to handle these cases?
For a), the more idiomatic alternative to CFRetain(foo)/CFRelease(foo) is [[NSGarbageCollector defaultCollector] disableCollectorForPointer:foo]/[[NSGarbageCollector defaultCollector] enableCollectorForPointer:foo].
Apple's recommendation is (c), but I like the sound of (b). A static data structure allows you to hide the GC details from the API user while avoiding dipping into the CFRetain/CFRelease level. As you state, it also makes debugging and unit testing easier; if an object is still referenced by the static data structure after it's finished its task, you know there's a bug.