Destroying self from within self - objective-c

I have an Objective-C class whose instances can detect when they are no longer needed and destroy themselves, but I am looking for a safe way to trigger an object's self-destruction from within the object itself, without somehow "destroying the method that is calling the destruction"... My code looks roughly like this (some removed for brevity):
+ (oneway void)destroyInstance:(id)obj {
printf("Destroying.\n");
if (obj != nil) {
free(obj);
obj = nil;
}
}
- (oneway void)release {
_noLongerRequired = [self determineIfNeeded]; // BOOL retVal
if (_noLongerRequired) {
[self deallocateMemory]; // Free ivars etc (NOT oneway)
[MyClass destroyInstance:self]; // Oneway
}
}
If I call -release, it should return instantly to the main thread (due to the oneway).
Meanwhile, if the instance finds it is no longer needed, it should then call the oneway class method destroyInstance: and remove itself from the runtime. My question is, is this safe?? And have I used oneway correctly? It seems to me there is the possibility of destroying the instance's -release function before it returns, which could be... rather bad..?
(PS: Obviously not looking for anything to do with NSObject, etc :))

This is without a doubt a terrible idea if you want working and maintainable software and unsafe in just about any context. But sometimes terrible, unsafe ideas can be fun on the weekend, so I'll answer the components of the question I can discern.
A method will not get "destroyed" because an instance is deallocated. What can happen is that self can end up pointing to deallocated memory during the execution of a method, which means that accessing self or any instance variables during this time can crash.
As to the rest of your code, there is no reason at all to set obj equal to nil in +destroyInstance, so if you were trying accomplish something in particular (nil'ing out pointers to the object perhaps) that way is not the right way to go about it.
Thinking about the use of oneway, what the language says is that sending this message won't block the calling thread. In the context of releasing objects I think it makes some sense, as presumably the target of the message won't ever be referenced by that thread again. By that logic I'd think your declaration of +destroyInstance is maybe OK. I do wonder if you'd need to provide some sort of synchronization so that there's no retain/release race conditions but thinking about it, taking ownership of an object should probably never be asynchronous.
My personal opinion is that anyone who puts this code into production should probably be fired or sued =P. But if it's only for educational purposes, have fun, and hope this helps.

Related

Passing in argument to method: Should argument be retained?

If I have a custom method like this:
- (void)myMethod:(id)myArgument
{
//do something with myArgument
}
is myArgument guaranteed to stick around for the execution of that method if i don't take ownership of it?
EDIT
Let me elaborate further. Say i call this somewhere:
[self myMethod:_myIvar];
and then somewhere else, while myMethod is executing, someone calls this:
[_myIvar release];
does that effect the argument within myMethod?
END EDIT
Looking through documentation/sample code, i rarely see a [myArgument retain] or [myArgument copy] at the top of a custom method. So is it unnecessary?
Thanks!
If myArgument is a valid object at the start of myMethod, and you do nothing to cause it to be deallocated or otherwise collected during the method, then yes, myArgument will still be a valid object at the end of the method.
EDIT in response to question's edit: let's talk about object ownership in this case. When you're passed myArgument as an argument to your function, you - in the context of myMethod - don't declare an interest in the object by retaining or copying it. In such a situation, the only owners of the object exist outside myMethod.
If the last owner of myArgument decides that it's done with myArgument and releases it, then it's entirely possible that myArgument goes away - there are no strong references to the object any more that would keep it around. It may be valid, depending on threading concerns, autorelease pools involved, and a whole host of other issues, but that's a dangerous game to play. If there's even a possibility that such a situation might happen, you should explicitly declare an interest in myArgument within myMethod, as recommended by the Memory Management Policy.
If it is even possible that another thread can cause the object referenced by myArgument to be deallocated then myArgument can become a pointer to junk memory at any time and you will crash.
This is nothing to do with not retaining it in -myMethod. You are just as likely to crash during the retain method call. Rather you have a broken, unworkable threading model / architecture in your app that you must fix.
This is why threading is hard.
No it is not guaranteed. You should call retain on anything you wish to keep hold of and release when finished. Otherwise another thread and dealloc it in the meantime.
I've had that bite me when writing an A* algorithm for a game.

how to use pointers in Objective c

I have seen some iOS developpers using code like this :
- (void)setupWebView:(UIWebView**)aWebView {
UIWebView *webview = [[UIWebView alloc] init];
.....
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
}
Do you know what'is this mean and why we use this ? thanks
- (void)setupWebView:(UIWebView**)aWebView {
That is awful. You should never have a method that returns void, but sets an argument by reference unless:
• there are multiple arguments set
• the method is prefixed with get
That method should simply return the created instance directly. And this just makes it worse -- is flat out wrong:
if (*aWebView) {
[*aWebView release];
}
*aWebView = webview;
it breaks encapsulation; what if the caller passed a reference to an iVar slot. Now you have the callee managing the callers memory which is both horrible practice and quite likely crashy (in the face of concurrency, for example).
it'll crash if aWebView is NULL; crash on the assignment, specifically.
if aWebView refers to an iVar slot, it bypasses any possible property use (a different way of breaking encapsulation).
It is a method to initialize a pointer. The first line allocates the object. The if statement makes sure that the passed in pointer-to-a-pointer is not already allocated, if it is it releases it. then it sets the referenced pointer to the newly allocated object.
The answer by #bbum is probably correct, but leaves out one aspect to the question that I see there. There are many examples in Foundation which use pointer-pointers in the method signature, so you can say it is a common pattern. And those are probably not a beginners mistake.
Most of these examples are similar in that they fall into one category: the API tries to avoid the usages of exceptions, and instead use NSError for failures. But because the return value is used for a BOOL that signals success, an NSError pointer-pointer is used as output parameter. Only in the probably rare error case an NSError object is created, which can contain error code and error descriptions, and localized descriptions and possibly even more information (like an array of multiple errors in the case of bulk operations). So the main success case is efficient, and the error case has some power to communicate what went wrong, without resorting to exceptions. That is the justification behind these signatures as I understand it.
You can find examples of this usage in both NSFileManager and NSManagedObjectContext.
One might be tempted to use pointer-pointers in other cases where you want multiple return values and an array does not make sense (e.g. because the values are not of same type), but as #bbum said, it is likely better to look hard for alternatives.

Using #synchronized(self) { ... } in class-function

Accidentally I have been using a #synchronized block with the semaphore self in a class method.
+(void)someFunction {
#synchronized(self) {
/* some code */
}
}
It seems to be valid code, at least the compiler does not give me any bad feedback. My question is: what is self here? As far as I can tell the #synchronized block didn't work, but it didn't crash either.
I'm just asking out of curiousity.
self in this instance refers to the class, instead of an instance. In ObjC, classes are themselves objects.
self in this context is the class itself, it's perfectly fine to use #synchronized in a class function since they are also Objective-C objects.
The #synchronized syntax is a compiler extension for mutex implementation. I assume you understood what it does. The compiler will translate it into something else, supposedly something similar to critical section because it's less CPU intensive. Locks need to be tracked. The implementation will use an object to record the state of the lock, to keep its integrity (i.e. a lock shouldn't be acquired twice, or unlocked twice).
In #synchronized(self), the object doesn't have to be self. It could be any objective-c object. Note that a single #synchronized block usually does nothing (when you mentioned it's not working, it's actually behaving correctly). But when you have two #synchronized blocks on the same object, only one block will be executed at the same time, the other block would have to wait for the lock to be unlocked (i.e. the first block finishes). This helps to keep things synchronized as in a multithreaded environment.
In a class method self is the class that the method is being called on. For example you can call other class methods of the same class using self. [MyClass someFunction] and [self someFunction] would be the equivalent to recursively calling someFunction. The #synchronized block I am sure worked as it was supposed to.

Calling a block from within an inner block

I have a Cocoa/Objective-C class with a method that looks something like this:
- (void)doWork:(void (^)(void))handler
{
[self->someObject doActualWork:kWorkID handler:^(Result *result) {
if (handler)
handler();
}];
}
However, when the inner block is called handler have been dealloced and the program crashes when it is called. From what I understand this is because the block is stored on the stack and thus removed soon after doWork: finishes. I'm using ARC. What should I do to fix this?
First, self-> for iVar access is an odd, and discouraged, pattern, generally.
Did you copy the blocks prior to storing 'em away for use later? If this is intended to be asynchronous code, then your actualWork:handler: method should be copying the block prior to enqueueing it.
Even under ARC; while ARC handles the return of blocks from methods automatically, it can't handle blocks as arguments automatically and you do still need to copy 'em.
If this is purely synchronous code, then something else is going wrong. You'll need to provide more clues.

can we override alloc and dealloc in objective C?

I know that this is rarely required to override the alloc or dealloc methods,but if required is it possible in iPhone programming?
You can and indeed, you should (if using manual memory management) override dealloc to release any resources you hold (not forgetting to call [super dealloc] when finished). Overriding alloc is possible but, as you say, rarely needed.
In general, overriding alloc is only done when you wish to, eg, allocate an object from a pool of available instances, or perhaps allocate a variable amount of storage for the object based on some external parameter. (In C++ you can access the new parameters and allocate based on them, but Objective-C does not give you access to the initXXX parameters.)
I've never attempted any of this, and I suspect that its a bit of a minefield -- you need to study up on the structures and be pretty careful.
As Adam said, you should ALWAYS (in a reference counted environment) override dealloc if there are any retained objects held by your object.
Update: An interesting thing you can do ... in RedClass or a superclass of it code something like:
+(id)alloc {
if (self == [RedClass class]) {
return [BlueClass alloc];
}
else {
return [super alloc];
}
}
The net result is that whenever you execute [RedClass alloc] a BlueCLass object will be returned. (NB: Presumably BlueClass is a subclass of RedClass, or things will get seriously mucked up shortly after the object is returned.)
Not saying that it's a good idea to do this, but it's possible (and I don't offhand know of any cases where it wouldn't work reliably for vanilla user-defined classes). And it does have a few possible uses.
Additional note: In some cases one might want to use [self isSubclassOf:[RedClass class]] rather than == (though that has some serious pitfalls).