Thread-safety of method swizzling - objective-c

Method swizzling is used in the following singleton initializer but i am not sure about thread safety of swizzling.
What happens while a thread is about to call a method which is about to be swizzled by another method?
Is it safe to swizzle in any time, while there are threads about to call that method? Answer with official references please. Thanks
#import <dispatch/dispatch.h>
#import <objc/runtime.h>
#implementation MySingleton
static MySingleton * __singleton = nil;
+ (MySingleton *) sharedInstance_accessor
{
return ( __singleton );
}
+ (MySingleton *) sharedInstance
{
static dispatch_once_t __once = 0;
dispatch_once( &__once, ^{
__singleton = [[self alloc] init];
Method plainMethod = class_getInstanceMethod( self, #selector(sharedInstance) );
Method accessorMethod = class_getInstanceMethod( self, #selector(sharedInstance_accessor) );
method_exchangeImplementations( plainMethod, accessorMethod );
});
return ( __singleton );
}
#end
https://gist.github.com/MSch/943369

I doubt there is an official reference on this, but none is needed.
First, the executable code of the method is not un-mapped from memory. Thus, it doesn't matter which implementation is installed, the prior implementation is still available for execution.
That does mean, however, that you have to ensure that your data management is thread safe (which it is, assuming no one tries to call sharedInstance_accessor directly).
So that leaves a question as to whether method_exchangeImplementations() is thread safe. The source says it is (and it was not several major release prior) and so does the documentation.
As Brad Allred said, this is unlikely to be an optimization worth pursuing.

According to the documentation, method_exchangeImplementations() is atomic. Presumably that means that if one of the two methods being exchanged is called from another thread at the same time as method_exchangeImplementations() is being run, it may get the previous (non-swapped) method, but it won't get something inconsistent (e.g. won't crash).
Note that dispatch_once() is thread safe, and also means that as long as all references to the singleton instance are obtained via +sharedInstance, no thread will have a reference to the object before the swizzling is complete.
Finally, I don't normally like adding this kind of thing to answers, because I realize that sometimes questioners are just trying to learn more about how things work, rather than trying to write production code. However, if you're planning to use this in real, shipping code, you should rethink it. Swizzling tends to be a "bad code smell", and it's likely that there's a better way to do whatever it is you're trying to accomplish (which is still not clear to me).

Related

Objective-C: How to force a call to `+initialize` at startup rather than later when the class happens to used for the first time?

Problem
For certain classes, I would like to explicitly call the +initialize method when my program starts, rather than allowing the runtime system to call it implicitly at some nondeterministic point later when the class happens to first be used. Problem is, this isn't recommended.
Most of my classes have little to no work to do in initialization, so I can just let the runtime system do its thing for those, but at least one of my classes requires as much as 1 second to initialize on older devices, and I don't want things to stutter later when the program is up and running. (A good example of this would be sound effects — I don't want sudden delay the first time I try to play a sound.)
What are some ways to do this initialization at startup-time?
Attempted solutions
What I've done in the past is call the +initialize method manually from main.c, and made sure that every +initialize method has a bool initialized variable wrapped in a #synchronized block to prevent accidental double-initialization. But now Xcode is warning me that +initialize would be called twice. No surprise there, but I don't like ignoring warnings, so I'd rather fix the problem.
My next attempt (earlier today) was to define a +preinitialize function that I call directly instead +initialize, and to make sure I call +preinitialize implicitly inside of +initialize in case it is not called explicitly at startup. But the problem here is that something inside +preinitialize is causing +initialize to be called implicitly by the runtime system, which leads me to think that this is a very unwise approach.
So let's say I wanted to keep the actual initialization code inside +initialize (where it's really intended to be) and just write a tiny dummy method called +preinitialize that forces +initialize to be called implicitly by the runtime system somehow? Is there a standard approach to this? In a unit test, I wrote...
+ (void) preinitialize
{
id dummy = [self alloc];
NSLog(#"Preinitialized: %i", !!dummy);
}
...but in the debugger, I did not observe +initialize being called prior to +alloc, indicating that +initialize was not called implicitly by the runtime system inside of +preinitialize.
Edit
I found a really simple solution, and posted it as an answer.
The first possible place to run class-specific code is +load, which happens when the class is added to the ObjC runtime. It's still not completely deterministic which classes' +load implementations will be called in what order, but there are some rules. From the docs:
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ __attribute__(constructor)
functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s +load method is called after all of its superclasses’ +load
methods.
A category +load method is called after the class’s own +load method.
So, two peer classes (say, both direct NSObject subclasses) will both +load in step 2 above, but there's no guarantee which order the two of them will be relative to each other.
Because of that, and because metaclass objects in ObjC are generally not great places to set and maintain state, you might want something else...
A better solution?
For example, your "global" state can be kept in the (single) instance of a singleton class. Clients can call [MySingletonClass sharedSingleton] to get that instance and not care about whether it's getting its initial setup done at that time or earlier. And if a client needs to make sure it happens earlier (and in a deterministic order relative to other things), they can call that method at a time of their choosing — such as in main before kicking off the NSApplication/UIApplication run loop.
Alternatives
If you don't want this costly initialization work to happen at app startup, and you don't want it to happen when the class is being put to use, you have a few other options, too.
Keep the code in +initialize, and contrive to make sure the class gets messaged before its first "real" use. Perhaps you can kick off a background thread to create and initialize a dummy instance of that class from application:didFinishLaunching:, for example.
Put that code someplace else — in the class object or in a singleton, but in a method of your own creation regardless — and call it directly at a time late enough for setup to avoid slowing down app launch but soon enough for it to be done before your class' "real" work is needed.
There are two problems here. First, you should never call +initialize directly. Second, if you have some piece of initialization that can take over a second, you generally shouldn't run it on the main queue because that would hang the whole program.
Put your initialization logic into a separate method so you can call it when you expect to. Optionally, put the logic into a dispatch_once block so that it's safe to call it multiple times. Consider the following example.
#interface Foo: NSObject
+ (void)setup;
#end
#implementation Foo
+ (void)setup {
NSLog(#"Setup start");
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(#"Setup running");
[NSThread sleepForTimeInterval:1]; // Expensive op
});
}
#end
Now in your application:didFinishLaunchingWithOptions: call it in the background.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"START");
// Here, you should setup your UI into an "inactive" state, since we can't do things until
// we're done initializing.
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[Foo setup];
// And any other things that need to intialize in order.
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(#"We're all ready to go now! Turn on the the UI. Set the variables. Do the thing.");
});
return YES;
}
This is how you want to approach things if order matters to you. All the runtime options (+initialize and +load) make no promises on order, so don't rely on them for work that needs that. You'll just make everything much more complicated than it needs to be.
You may want to be able to check for programming errors in which you accidentally call Foo methods before initialization is done. That's best done, IMO, with assertions. For example, create an +isInitialized method that checks whatever +setup does (or create a class variable to track it). Then you can do this:
#if !defined(NS_BLOCK_ASSERTIONS)
#define FooAssertInitialized(condition) NSAssert([Foo isInitialized], #"You must call +setup before using Foo.")
#else
#define FooAssertInitialized(condition)
#endif
- (void)someMethodThatRequiresInitialization {
FooAssertInitialized();
// Do stuff
}
This makes it easy to mark methods that really do require initialization before use vs ones that may not.
Cocoa provides a setup point earlier than +initialize in the form of +load, which is called very shortly after the program's start. This is a weird environment: other classes that rely on +load may not be completely initialized yet, and more importantly, your main() has not been called! That means there's no autorelease pool in place.
After load but before initialize, functions marked with __attribute__((constructor)) will be called. This doesn't allow you to do much that you can't do in main() so far as I know.
One option would be to create a dummy instance of your class in either main() or a constructor, guaranteeing that initialize will be called as early as possible.
Answering my own question here. It turns out that the solution is embarrassingly simple.
I had been operating under the mistaken belief that +initialize would not be called until the first instance method in a class is invoked. This is not so. It is called before the first instance method or class method is invoked (other than +load, of course).
So the solution is simply to cause +initialize to be invoked implicitly. There are multiple ways to do this. Two are discussed below.
Option 1 (simple and direct, but unclear)
In startup code, simply call some method (e.g., +class) of the class you want to initialize at startup, and discard the return value:
(void)[MyClass class];
This is guaranteed by the Objective-C runtime system to call [MyClass initialize] implicitly if it has not yet been called.
Option 2 (less direct, but clearer)
Create a +preinitialize method with an empty body:
+ (void) preinitialize
{
// Simply by calling this function at startup, an implicit call to
// +initialize is generated.
}
Calling this function at startup implicitly invokes +initialize:
[MyClass preinitialize]; // Implicitly invokes +initialize.
This +preinitialize method serves no purpose other than to document the intention. Thus, it plays well with +initialize and +deinitialize and is fairly self-evident in the calling code. I write a +deinitialize method for every class I write that has an +initialize method. +deinitialize is called from the shutdown code; +initialize is called implicitly via +preinitialize in the startup code. Super simple. Sometimes I also write a +reinitialize method, but the need for this is rare.
I am now using this approach for all my class initializers. Instead of calling [MyClass initialize] in the start up code, I am now calling [MyClass preinitialize]. It's working great, and the call stack shown in the debugger confirms that +initialize is being called exactly at the intended time and fully deterministically.

Fully deallocating an Objective-C singleton

I'm new to writing singletons and I have to use one for a current iOS project. One of the requirements is that it can be killed. I know this goes against the design of a singleton, but is this something that should/could be done?
Of course it could be done, but if you're looking for an object that can be created, and then released when not needed... that sounds like a regular object. :)
Generally singletons control their own lifecycles. You're going to get one-sided discussion here unless you say more about the two requirements (one, that you use a singleton, and two, that it can be released at will), and why they both make sense in your case.
It might be because the singleton wraps some other resource that is inherently unique (like a file resource or network connection). If this is true, then generally the singleton is the "manager" of that resource, and you'd expose control of that resource via the singleton's interface.
Or it might be because the singleton object holds on to a ton of memory (a buffer of some sort), and you want to be sure that's flushed as necessary. If this is the case, then you can be smarter about each of its methods creating and releasing memory as necessary, or you can have the singleton listen for the low memory system notifications and behave appropriately.
Essentially, I'd be hard pressed to construct a case where it really made sense for the singleton object itself to be released. A single basic object takes only a handful of bytes in memory, and hurts no one by hanging around.
I know this goes against the design of a singleton
It also goes against the usual memory management patten in Objective-C. Normally, an object gets to retain another object to prevent it from being destroyed, and to release it to allow the object to be destroyed. Explicitly destroying an object, though, isn't something that other objects get to do.
Consider what would happen if object A gets the shared instance S1 of a singleton class S. If A retains S1, S1 will continue to exist even if some class method releases S and sets the global variable that points to the shared instance to nil. When the class later creates a new shared instance, S2, there will be two instances of S, namely S1 and S2. This violates the property that defines the singleton in the first place.
You might be able to get around this problem by overriding -retain and maybe swizzling -release, but that seems like a lot of complexity to solve a problem that shouldn't exist in the first place.
A possible alternative is to reset your shared object instead of trying to destroy it. You could set all it's attributes to some known (possibly invalid) state if you want, and then have a class method the re-initializes the shared object. Just be aware of the effect of all that on any objects that might be using the shared object.
Just about every singleton I've ever written (save for totally UI centric controllers) end up being refactored into not being singletons. Every. Single. One.
Thus, I've stopped writing singletons. I write classes that maintain state in instances, as any normal class should, and do so in isolation from other instances. If they are notification heavy, they always pass self as the notifying object. They have delegates. They maintain internal state. They avoid globals outside of truly global state.
And, often, there may be exactly one instance of said class in my app(s). That one instance acts like a singleton and, in fact, I might even create a convenient way of getting a hold of it, likely through the App's delegate or through a class method (that might even be named sharedInstance sometimes).
Said class includes tear-down code that is typically divided in two pieces; code to persist current state for restoration later and code that releases instance associated resources.
Convenient like a singleton. Ready to be multiply instantiated when needed.
Sure no problem. You provide a new class method: [MyClass killSingleton]; That method releases the singleton and sets its internal reference to nil. The next time someone asks [MyClass sharedSingleton], you go through the same steps you did before to create it.
EDIT: actually, in the old days such a routine could have overridden the release selector, and refused to go away. So as the first comment below states, this is an object with static scope - its kept alive through a static variable keeping a retain count of 1 on the object. However, by adding in a new class method to nil out that ivar (under ARC), thereby releasing it, achieves the desired result. Control over instantiating and releasing the static object is completely done via class methods, so is easy to maintain and debug.
It's against the concept of Singleton, but it can be implemented the following way for an ARC based project
//ARC
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
+ (void)selfDestruct;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[Singleton alloc] init];
}
return sharedInstance;
}
+ (void) selfDestruct {
sharedInstance = nil;
}
#end
//This can be implemented using bool variable. If bool no create new instance.
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (!keepInstance) {
sharedInstance = [[Singleton alloc] init];
keepInstance = YES;
}
return sharedInstance;
}
#end
I needed to clear out the singleton so I ended up doing the following:
- (void)deleteSingleton{
#synchronized(self) {
if (sharedConfigSingletone != nil) {
sharedConfigSingletone = nil;
}
}
}
Hope it helps.

Manual object lifetime with ARC

Examine the following code, and assume it was compiled under ARC:
- (void)foo {
NSOperationQueue *oq = [[NSOperationQueue alloc] init];
[oq addOperationWithBlock:^{
// Pretend that we have a long-running operation here.
}];
}
Although the operation queue is declared as a local variable, its lifetime continues beyond the scope of the method as long as it has running operations.
How is this achieved?
UPDATE:
I appreciate Rob Mayoff's well-thought-out comments, but I think I did not ask my question correctly. I am not asking a specific question about NSOperationQueue, but rather a general question about object lifetime in ARC. Specifically, my question is this:
How, under ARC, can an object participate in the management of its own lifetime?
I've been a programmer for a very long time, and I'm well aware of the pitfalls of such a thing. I am not looking to be lectured as to whether this is a good or bad idea. I think in general it is a bad one. Rather, my question is academic: Whether it's a good or bad idea or not, how would one do this in ARC and what is the specific syntax to do so?
As a general case you can keep a reference to yourself. E.g.:
#implementation MasterOfMyOwnDestiny
{
MasterOfMyOwnDestiny *alsoMe;
}
- (void) lifeIsGood
{
alsoMe = self;
}
- (void) woeIsMe
{
alsoMe = nil;
}
...
#end
Here are a few possibilities:
The NSOperationQueue retains itself until it is empty, then releases itself.
The NSOperationQueue causes some other object to retain it. For example, since NSOperationQueue uses GCD, perhaps addOperationWithBlock: looks something like this:
- (void)addOperationWithBlock:(void (^)(void))block {
void (^wrapperBlock)(void) = ^{
block();
[self executeNextBlock];
};
if (self.isCurrentlyExecuting) {
[self.queuedBlocks addObject:wrapperBlock];
} else {
self.isCurrentlyExecuting = YES;
dispatch_async(self.dispatchQueue, wrapperBlock);
}
}
In that code, the wrapperBlock contains a strong reference to the NSOperationQueue, so (assuming ARC), it retains the NSOperationQueue. (The real addOperationWithBlock: is more complex than this, because it is thread-safe and supports executing multiple blocks concurrently.)
The NSOperationQueue doesn't live past the scope of your foo method. Maybe by the time addOperationWithBlock: returns, your long-running block has already been submitted to a GCD queue. Since you don't keep a strong reference to oq, there is no reason why oq shouldn't be deallocated.
In the example code give, under ARC, the NSOperationQueue, being local to the enclosing lexical scope of the block, is captured is captured by the block. Basically, the block saves the value of the pointer so it can be accessed from within the block later. This actually happens regardless of whether you're using ARC or not; the difference is that under ARC, object variables are automatically retained and released as the block is copied and released.
The section "Object and Block Variables" in the Blocks Programming Topics guide is a good reference for this stuff.
The simplest thing I can think of would be to have a global NSMutableArray (or set, or whatever) that the object adds itself to and removes itself from. Another idea would be to put the (as you've already admitted) oddly-memory-managed code in a category in a non-ARC file and just use -retain and -release directly.

iPhone SDK: When allocating a static variable, should I check for nil?

I often see singleton classes designed similar to the following:
#implementation SomeImplementation
static SomeClass *sharedSomeObject = nil;
+ (void) someClassMethod {
sharedSomeObject = [[SomeImplementation alloc] init];
// do something
}
#end
someClassMethod can be called at any time -- should it be checking for nil first before allocating a new instance of sharedSomeObject? Or, since sharedSomeObject is static, is the check unnecessary? Seeing code like this I always want to put an if (!sharedSomeObject) around the allocation.
Yes, absolutely! Otherwise you're creating more than one object every time your method is called. This is how we do things:
+ (SomeClass *) shared {
static SomeClass *sSingleton;
if ( ! sSingleton ) sSingleton = [SomeClass new];
return sSingleton;
}
EDIT
This answer is very old, not thread-safe, and no longer an appropriate singleton initialization method. See this Stackoverflow answer for the correct way of doing things nowadays with GCD.
When it comes to the using the Singleton design pattern with Objective-C, I can highly recommend using Matt Galagher's "SynthesizeSingleton.h" macro. It deals with all the singelton-related topics like freeing (is that a proper word?) memory if the singleton will be no longer needed.
Here's the link to the "Cocoa with Love" website which contains an article on this topic as well as a link for the download of the "SynthesizeSingleton.h" header file:
http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
You will also find a discussion on using global variables vs. using the Singleton design pattern as well as some considerations on different approaches towards using Singletons there.

Is there a bug in NSOperation in Mac OS X 10.6?

If I release an instance of NSOperation before sending -init to it I get a segmentation fault.
Reasons I think this is valid code:
Apple does this in its documentation.
Gnustep does it in its implementation of NSNumber, so it's fairly certain that this is in Apple's code too. (At least was.)
NSObjects -init doesn't do anything, therefore -release, which belongs to NSObject should be working before that.
// gcc -o test -L/System/Library/Frameworks -framework Foundation test.m
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
NSOperation *theOperation = [NSOperation alloc];
[theOperation release];
}
What do you think, is this a bug?
Can you show me an example of another class that has the same behavior?
Any idea why this is happening?
Sending any message other than init to an object that has not been initialized is not valid code AFAIK. Call the superclass initializer and then release and I'm betting it won't crash (although having one class's initializer return a completely unrelated class strikes me as doubleplusungood).
There is nothing remotely valid about that code.
Rewrite your -init as:
- (id) init
{
if (self = [super init]) {
[self release];
NSNumber *number = [[NSNumber alloc] initWithInteger:6];
return number;
}
return self;
}
Of course, the code is still nonsense, but it doesn't crash.
You must always call through to the super's initializer before messaging self. And you must always do it with the pattern shown above.
I thought you need to initialize your superclass before calling release, but according to this example in Apple's docs that's not the case.
So it may be a bug, but certainly not an important one.
My previou analysis was not really correct.
However, I want to point that this issue can happen with different classes. It actually depends on which class you're subclassing. Subclassing NSObject is no problem, but subclassing NSOperation, NSOperationQueue, and NSThread is an issue, for example.
And it happens because just like YOU might do, the classes you subclass might allocate stuff in their -init method. And that's also where you set to nil the variables you have not allocated yet (and might do so later in your code).
So, by calling -release on yourself without a previous -init, you might cause one of your parent classes to release object that it had not allocated. And they can't check if their object is nil, because it didn't even have the opportunity to init every object/value it needs.
This also might be the reason why releasing NSOperation without init worked on 10.5 and doesn't work on 10.6. The 10.6 implementation have been rewritten to use blocks and Grand Central Dispatch, and thus, their init and dealloc methods might have changed greatly, creating a different behavior on that piece of code.