mikeash.com: just this guy, you know?

Posted at 2009-10-02 15:59 | RSS feed (Full text feed) | Blog Index
Next article: Friday Q&A 2009-10-09: Defensive Programming
Previous article: Friday Q&A 2009-09-25: GCD Practicum
Tags: cocoa fridayqna objectivec singleton
Friday Q&A 2009-10-02: Care and Feeding of Singletons
by Mike Ash  

It's time for another Friday Q&A. I hope everyone who had a chance to go to C4 had a good time and is back home safe and sound. This week I'm going to discuss singletons, both how to make them and when to use them, as suggested by Jon Trainer.

What Is It?
Most of you probably know this already, but for the sake of completeness, a singleton is an object which is restricted to be the only instance of its class. In other words, within any given process, you have the concept of the Foo, rather than a Foo.

Benefits
Why would you use a singleton instead of a regular class? There are a few basic reasons:

  1. Global access: A singleton is essentially shared throughout the entire program, making it easier to coordinate activities. A major example of this in Cocoa is NSNotificationCenter.
  2. Resource management: Having a single instance of a class is appropriate if that class represents an entity which is inherently singular. An example of this in Cocoa is NSApplication.
  3. Grouping functionality: Sometimes you have a lot of similar functionality that logically goes together but which doesn't necessarily fit into the object model because there's no long-term state. By using a singleton you simplify access to this functionality. NSWorkspace is an exmple of this usage of a singleton in Cocoa.
  4. Lazy initialization: Properly-written singleton classes aren't instantiated until something asks for them, meaning that the resources occupied by the singleton aren't allocated until they're needed.
Downsides
Singletons aren't always appropriate. (In fact, they're almost always not appropriate. Just look at the proprotion of singletons to normal classes in any given program.) In general you should not use one unless you need it, but there are some specific pitfalls to look out for:
  1. Shared global state: Singletons are inherently globally accessible, which means that any state which exists as part of the singleton can be accessed and potentially changed from any part of the program. Good encapsulation of singleton state can help with this a lot, but if you're not careful then the problem can be much like that of global variables. This can be particularly vicious in a multithreaded environment. Many Cocoa singletons suffer from not being thread safe and their global accessibility makes them inherently limited to only being used from the main thread.
  2. Over-specialized code: You thought there would only be one, so you made a singleton around it. Now there are two. All of your code assumes that there is only one. Time for a big, painful rewrite.

How to Make One
At its most basic, a singleton is implemented like this:

    + (id)sharedFoo
    {
        static Foo *foo = nil;
        if(!foo)
            foo = [[self alloc] init];
        return foo;
    }
That's it! You're done!

Right about now, a bunch of people are thinking back to a certain Apple document on singletons which shows a much more complicated implementation. There are basically two advantages to Apple's version which this doesn't have.

  1. Thread safety: Apple's version correctly deals with the case where multiple threads try to access the singleton before it's been created.
  2. Programmer safety: Apple's version tries to cover for a lot of dumb mistakes a programmer might make, like incorrectly releasing a singleton.
Thread safety is useful but not always necessary. Programmer safety is, in my opinion, counterproductive. Apple's approach, of building a singleton which can't be destroyed by accident and which intercepts attempts to allocate a second instance, covers up errors rather than fixing them. It's much better to trap and eliminate the bad code rather than render it harmless. For example, instead of overriding release to do nothing, override dealloc to log an error and abort the program.

Furthermore, it's not always necessary to really strictly enforce singleton-ness. NSFileManager is a good example of this from Cocoa. Through 10.4 it was a singleton, and not thread safe and thus could only be used on the main thread. Starting in 10.5, Apple allowed the creation of separate instances which could then be safely used on other threads. Your code might well want to do the same thing. Often, providing the shared globally-accessible instance is the major benefit of having a singleton, and there's no need to prohibit other instances being created on the side.

This brings up one tip I want to mention regarding singletons: always implement a dealloc method and keep it up to date. With a singleton, it's tempting to forget about releasing resources because it will live for the life of the program. But it's much easier to write code to release resources as you write the rest of the code than it is to add it in later, and you'll be glad you did if you ever decide to make your singleton no longer be single.

Thread Safe Singletons
What about when thread safety is necessary?

One really simple way to deal with this is to simply toss in a lock, like so:

    + (id)sharedFoo
    {
        static Foo *foo = nil;
        @synchronized([Foo class])
        {
            if(!foo)
                foo = [[self alloc] init];
        }
        return foo;
    }
Now your singleton can be safely accessed from multiple threads.

Note: this makes it safe to retrieve the shared singleton from multiple threads, but does not automatically make it safe to use it. Making the singleton's code be thread safe is up to you!

This code is kind of slow, though. Taking a lock is somewhat expensive. Making it more painful is the fact that the vast majority of the time, the lock is pointless. The lock is only needed when foo is nil, which basically only happens once. After the singleton is initialized, the need for the lock is gone, but the lock itself remains.

One fix for this is to take advantage of the Objective-C runtime and use the +initialize method instead:

    static Foo *gSharedFoo;
    
    + (void)initialize
    {
        if(self == [Foo class])
            gSharedFoo = [[self alloc] init];
    }
    
    + (id)sharedFoo
    {
        return gSharedFoo;
    }
The runtime takes care of all the nasty locking stuff for you, and ensures that +initialize always runs before +sharedFoo can execute. The only downside to this approach is that +initialize will run if any message is sent to your class, possibly initializing the singleton earlier than necessary.

Double-Checked Locking
If you search on the above phrase you'll find a bunch of web pages talking about how this technique is a bad idea. And it is, for platform-independent code. However, if you can assume some knowledge of your target platform (and hey, we're all doing OS X development here) then it can be done safely.

The basic concept of double-checked locking is to have two copies of the if statement that checks to see if the singleton has been initialized. An outer if statement checks to see if the singleton is initialized. If it is, then return it, no lock taken. If it's not, then take the lock and check the singleton again. This ensures that all threads which might try to initialize the singleton are synchronized via the lock.

The problem with this approach is out-of-order memory access, either generated by the compiler or performed by the CPU. For more information on this, you can read my article on using the volatile keyword in a multithreaded context.

The solution to the CPU side is to insert a memory barrier when writing and when reading. Memory barriers enforce in-order access to memory locations by the CPU. In OS X, a memory barrier function is available in the libkern/OSAtomic.h header, called OSMemoryBarrier. The solution to the compiler side is to use volatile on the shared variable.

Thus our double-checked locking singleton method looks like this:

    + (id)sharedFoo
    {
        static Foo * volatile foo = nil;
        if(!foo)
        {
            @synchronized([Foo class])
            {
                if(!foo)
                {
                    Foo *tmpFoo = [[self alloc] init];
                    OSMemoryBarrier();
                    foo = tmpFoo;
                }
            }
        }
        OSMemoryBarrier();
        return foo;
    }
This is better than taking a lock every time, but we still have to pay for the memory barrier. It probably doesn't matter at all, and this smacks of premature optimization, but it grates to have that in there.

Grand Central Dispatch
If you can target 10.6+, Grand Central Dispatch provides an extremely fast one-time initialization API which is perfect for a singleton. Not only is it fast, but it's also extremely easy to use. It's a win all around!

Here's what the GCD solution looks like:

    + (id)sharedFoo
    {
        static dispatch_once_t pred;
        static Foo *foo = nil;
        
        dispatch_once(&pred, ^{ foo = [[self alloc] init]; });
        return foo;
    }
The dispatch_once function takes care of all the necessary locking and synchronization. It's actually a macro which expands to something much like the double-checked locking solution above. However, using some extremely underhanded trickery, it doesn't even need to take the hit of a memory barrier. In the common case, this code is a single if check followed by a return. Aside from the fact that it's examining two variables instead of one (an extremely small cost) it's as fast as the non-thread-safe version I started out with, and very nearly as simple. Nice!

Advanced Topics
There are a couple of interesting advanced techniques with singletons that I want to cover briefly. I won't go over how to build them, but think of them as exercises for the reader.

One such thing is an automatic singleton class. This would be a class which you subclass and which automatically provides all the necessary infrastructure to provide a singleton of that class. The superclass would have a method which returns (and creates, if necessary) the singleton instance of the subclass on which it was invoked. Managing the singletons would probably involve a global dictionary mapping classes to their singleton instances.

Another interesting variant, which I've never actually seen implemented, is a destroyable singleton. Rather than create a single shared instance which lives forever, the singleton accessor would not take ownership of the singleton object, and would allow it to be destroyed when all other code gives up ownership of it. In Cocoa, this would be accomplished by returning an autoreleased singleton, or when programming with garbage collection, by using a __weak global to store it. Making this thread safe would be a challenge, to ensure that duplicates aren't created but that old ones aren't ressurected as they're being destroyed.

Conclusion
That wraps up this week's edition. Now you know all about singletons, probably far more than you wanted to know.

Come back next week for another one. As always, Friday Q&A is driven by your submissions. The better the submissions I get, the better the articles you get to read! Send in your ideas for future articles today!

Did you enjoy this article? I'm selling a whole book full of them. It's available for iBooks and Kindle, plus a direct download in PDF and ePub format. It's also available in paper for the old-fashioned. Click here for more information.

Comments:

Georg at 2009-10-02 17:01:00:
Does dispatch_once() block if the block is currently being executed?

Steven Degutis at 2009-10-02 17:16:46:
Great article, in great depth. Thanks Mike! Your mention of how singletons may not always be singletons reminds me of the Universe example: we think there's only one universe, but we may discover later that there's more, and rewrite our scientific books (ie, a huge pain).

Curiously, assuming that an automatic singleton superclass is feasible and safe for production code, have you ever written or seen one? It seems to me like the perfect addition to my general-purpose Cocoa framework. (Granted, it's likely to almost always be the wrong answer, but the implementation of it is just tricky enough that it's annoying to rewrite over and over.)

Steven Degutis at 2009-10-02 17:26:10:
Mike:

I also wanted to point out that this code is generally not reentrant for the -init method. If the -init method calls the shared (or global) accessor, it will loop forever. The fix for this that I use is to assign the global variable as foo = [self alloc] first, then reassign and initialize it via foo = [foo init].

Jeff Johnson at 2009-10-02 17:30:24:
Mike, Objective-C has built-in singletons, namely, class objects. :-) How do you feel about using classes as singletons? Obviously you wouldn't be able to create multiple instances, but if you never need to do that, why create a shared instance of a class rather than using the class itself?

mikeash at 2009-10-02 17:32:10:
Georg: Yes, it blocks until the initializer block has completed, that's pretty much the whole point of it.

Steven Degutis: I think I've seen such things around (cocoadev.com maybe) but don't recall. As for reentrancy in the shared getter, reassigning is a bad idea, due to the fact that init can return a different object. Better would be to simply refer to self in your initializer, since that's what you're really after anyway.

mikeash at 2009-10-02 17:40:05:
Jeff Johnson: I don't like using class objects directly for a couple of reasons. One is that using static globals instead of ivars is somewhat annoying and unclean. Another is that it locks you into the singleton-ness of the code much more strongly. A well designed singleton can support multiple instances with little work if it should become necessary later on, but moving a class-singleton to support multiple instances is much less fun. Finally, it occasionally makes sense to subclass a singleton (e.g. NSApplication or NSDocumentController) and this doesn't really work when using a class object for one.

Overall I don't think it makes a big difference, but real instances are somewhat cleaner and not much harder.

Steven Degutis at 2009-10-02 17:50:45:
My take at Mike's challenge of an automatic singleton superclass... http://gist.github.com/199935 -- (my only gripe is the inconsistency in the accessor's name, compared to common Cocoa names like defaultCenter and sharedManager, etc.)

Jeff:

Not that I was asked, but I'd say the difference between singletons and a class with only class methods, are the instance variables. You would have to create a lot of static vars in your class, to act as ivars, and that just feels weird... not to mention, those pseudo-ivars aren't going to work well with things like KVC/KVO and @properties, and won't be accessible from within subclasses either, among other things.

Brent Royal-Gordon at 2009-10-02 18:49:34:
Hi, Mike. Thanks for the series—it's quite informative.

I'd love to hear about uniquing objects—that is, ensuring that only a single object of a given class with (say) a given ID number is allocated in the application at a time. I've done this a few times, but I've never worked out how to allow them to be deallocated when they're no longer used—and there may be other tricks I don't know about.

natevw at 2009-10-02 20:00:47:
What about something like:

+ (id)sharedFoo {
    static Foo* volatile foo = nil;
    if (!foo) {
        Foo* tmpFoo = [[self alloc] init];
        bool set = OSAtomicCompareAndSwapPtrBarrier(nil, tmpFoo, (void*volatile*)&foo);
        if (!set) [tmpFoo release];
    }
    return foo;
}

It would do a bit of wasted work if the first few calls do happen simultaneously, but is this a good solution for pre-GCD code?

Christopher Atlan at 2009-10-02 22:11:45:
Instead of dispatch_once there is also the POSIX pthread_once (http://opengroup.org/onlinepubs/007908799/xsh/pthread_once.html) out there.

mikeash at 2009-10-02 23:06:13:
Brent Royal-Gordon: I don't think I'd do this as an actual post, lacking experience in it, but here's the quickie summary.

If you're using garbage collection, then life is easy. Use an NSMapTable with weak objects. Wrap it in a lock if you need it to be thread safe.

Non-GC non-thread-safe is also fairly easy. Same NSMapTable setup, then have each cached object clear its own entry in -dealloc.

Non-GC thread-safe is a bit harder. You have to watch out for the case where one thread releases the last reference to a cached object, and then another thread tries to retrieve that reference before the object is actually removed from the NSMapTable. To avoid this, you'll probably want to implement your own reference counting mechanism (override retain/release) so that these are protected by the same lock that protects the NSMapTable.

natevw: I think that you also need an OSMemoryBarrier() before the return foo; for this to be 100% correct. (I think we discussed this before and I thought this was ok, but now I'm less certain.) And of course your singleton object needs to be able to tolerate multiple (unused) instances for a short period.

ChristopherAtlan: Yes, that will work fine as well, although it's a bit slower. I also don't like the fact that they don't support a context pointer to the function the way dispatch_once does. However, it's perfectly fine for this usage.

Linan Wang at 2009-10-03 01:09:32:
Instead of using:
static Foo *gSharedFoo;

I think it's a better to use the new associated object feature:

+(void)initialize{
  static dispatch_once_t pred;
  Foo *foo;

   dispatch_once(&pred, ^{
      foo = [[[self alloc] init] release];
      objc_setAssociatedObject(NSApp, @selector(sharedFoo), OBJC_ASSOCIATION_RETAIN);
   });

   return foo;
}

+(id)sharedFoo{
   return objc_getAssociatedObject(NSApp, _cmd);
}

mikeash at 2009-10-03 13:07:47:
Can you explain what makes this better? It looks slower, uglier, and more error prone (what if somebody else uses @selector(sharedFoo) as a key on NSApp too?) than just using a static global.

Linan Wang at 2009-10-03 22:11:16:
By getting rid of the static global, it's one step towards the ruby's way to implement singleton. I'm sure it's possible to work out a helper class like this:

@implementation SingletonHelper

+ (id)initializeSingletonClass:(Class)kls onceT:(dispatch_once_t)pred;
{
    // Add the [kls sharedKls] message
    NSString *msg_name = [NSString stringWithFormat:@"shared%@", NSStringFromClass(kls)];
    SEL sel = NSSelectorFromString(msg_name);
    Method m = class_getClassMethod(SingletonHelper, @selector(getSharedInstance));
    class_addMethod(kls, sel, method_getImplementation(m), "@@:");
    
    // initialize the shared instance, and return
    id ret;
    dispatch_once(&pred, ^{
        ret = [[[kls alloc] init] autorelease];
        objc_setAssociatedObject(NSApp, sel, OBJC_ASSOCIATION_RETAIN);
    });
    return ret;
    
}

+ (id)getSharedInstance;
{
    return objc_getAssociatedObject(NSApp, _cmd);
}

@end
(Codes are not tested yet.)

Then, to make a singleton class, all need to do is like this:
@interface ExampleSignleton : NSObject
{
}
@end


@implementation ExampleSignleton
+ (void)initialize
{
    static dispatch_once_t pred;
    [SingletonHelper initializeSingletonClass:[self class] onceT:pred];
}
@end

For the problem of using @selector(sharedFoo) as the key, I think there is nothing stops me (an individual programer) to create my own conventions, and, if my conventions are consistent within the scope of a project, it'll be fine.

mikeash at 2009-10-04 02:11:53:
Being "one step" towards this idea of a better singleton is pointless. Either the "one step" stands up on its own merit, or it doesn't. In this case, it doesn't. If you see the Ruby way as being superior, then you need to do all of it. Modifying code in ways which make it possible but which aren't useful in their own right really isn't very useful.

I have to say that I really don't see the point of using an associated object even in your more complicated case here. You're basically just using associated objects on NSApp as an ugly and dangerous thread-safe substitute for an NSMutableDictionary. Why not just use @synchronized and an NSMutableDictionary, then? Associated objects buy you nothing here: they make sense when you have a value which is, well, associated with another object. It makes no sense to associate singletons with NSApp.

Linan Wang at 2009-10-04 23:11:36:
Seems we have a taste dispute.
As far as I concern, my method is better in terms of code reuse. With the help of the class SingletonHelper, I need only additional 2 lines of codes to implement singleton on any classes. Of course it does cost something, a self-defined convention that all associated values of NSApp, starting with "shared", are singleton instances within the scope of an application. The trade-off, including little bit speed, is considered worthy.
I don't understand why you think static globals are prettier than associated values with NSApp? Singleton instances, after all, should be only available instances of certain classes within the scope of a running instance of NSApplication. Therefore, conceptually it's acceptable (if not perfectly) to bind those instances with NSApp. It is possible, as you suggested, to use a static global nsmutabledctionary to hold these singleton instances. But it is conceptually redundant. NSApp is like the "document" nod in a HTML dom, it's the root of everything. Is it conceptually clearer for you treat singleton instances "rootless" by using static globals?

mikeash at 2009-10-05 00:30:31:
Please understand, I'm not criticizing your idea of having a universal singleton class which you can subclass to get singleton-ness. I don't think it's particularly necessary (if you're creating that many singletons, you're probably doing something wrong) but there's nothing bad about it.

What I'm criticizing is two things:

1) That your initial proposal somehow had merit just because it was one step along a path to this universal singleton class. That's illogical. A step along a path does not have merit just because the end of the path does.

2) That associated objects on NSApp are better than static globals.

#1 I don't think needs any further explanation. If it's not obvious to you, then I can't convince you otherwise. The claim is a simple non sequitur.

#2 just makes no sense to me. Here is why I think that a static global is better:

- Works even when NSApp is not yet initialized.

- It's much clearer code.

- It's quite possibly faster, especially if you don't need to be thread safe.

- It will use less memory, since associated objects currently incur a 2kB memory cost for each object that has associated references on it. It's unlikely that anything else will use associated references on NSApp, so you'll cause that cost yourself.

- It works on any version of Mac OS X, not just 10.6+.

- It works for Foundation-only programs.

And for reasons why associated objects are better, I'm coming up completely empty. I can't see a single thing about it that's better.

Your comment that NSApp is the root of everything is nonsensical. You can have perfectly workable Objective-C programs that never have an NSApp. Global variables are how you do this in C. Trying to use HTML concepts in C just makes no sense.

If you can come up with an actual concrete advantage to your approach I'll certainly consider it, but so far it's nothing but handwaving.

Paul Marks at 2009-10-08 01:55:10:
A good example of your "destroyable singletons" is the concept (and implementation!) behind a CFBundleRef. Note that NSBundle does not share the behavior of being deallocated when client code is done; they live forever, but a CFBundleRef will be freed.

mikeash at 2009-10-08 02:46:37:
CFBundleRef isn't really a destroyable singleton, since you can have more than one. It's more like Brent Royal-Gordon's idea of uniqued objects. However, the two concepts are very similar. In both cases, you're returning an existing object when appropriate, letting objects be destroyed when no longer referenced, with the difference being only in how many instances you allow for.

Nikita Zhuk at 2009-10-10 16:15:57:
Additional downside of using Singletons is that they make unit testing very complicated or impossible if the code under test is calling methods of a global Singleton instance. A much better option is to declare all dependencies explicitly and inject dependencies as part of object graph construction. You can still have only one instance of some class (e.g. NSFileManager), but that's just a feature of your object graph construction code - you don't have to enforce it. Now if you want to mock your file system in unit tests, just pass your MockFileManager instead.

Martin Schuerrer at 2011-04-26 23:13:36:
Why not squeeze every last bit of performance out of the code and swizzle the sharedSingleton method after initialization (in the last line of the dispatch_once block)?

https://gist.github.com/943369

mikeash at 2011-04-27 02:15:38:
That looks fine, the only reason not to use it would just be because the code ends up being slightly more complicated. Regarding performance, I'm going to guess that the only performance consequence to the simpler version will be having more code in the instruction cache, as branch prediction will probably make the if statement itself free.

SP at 2012-10-30 14:42:00:
Hi Mike, Thanks a lot for the article.Inside the block you are using "self". Will not create classic retain cycle? Self will hold block & block will hold self.

+ (id)sharedFoo
    {
        static dispatch_once_t pred;
        static Foo *foo = nil;
        
        dispatch_once(&pred, ^{ foo = [[self alloc] init]; });
        return foo;
    }

Is not it better to do it like this?
+ (id)sharedFoo
    {
        static dispatch_once_t pred;
        static Foo *foo = nil;
        
        dispatch_once(&pred, ^{ foo = [[Foo alloc] init]; });
        return foo;
    }

Regards,
SP

mikeash at 2012-11-02 15:04:12:
Using self in a block only creates a retain cycle if the block is long-lived. In this case, the block is never even copied to the heap, much less kept alive for a long time.

dongzee at 2013-03-20 07:21:51:
In fact,I'd like the way by using dispatch_once.But now I meet a trouble: both considering thread-safe, loop for 1000 or more times, @synchronized cost a little less time than dispatch_once. It's Unexpected。Why?

eschatz at 2013-11-27 16:00:50:
hi Mike,

For the GCD version, how do we make sure that foo is not in a partially modified while another thread is about to assign new value to it? Could dispatch_once guarantee this?

I assume that primitive types(int,char,pointers i.e.) are assigned in an atomic way but i also remember your statement that access to * any pieces* of shared memory must be synchronized;

"In standard multithreaded code, you must synchronize access to any pieces of shared memory, usually by using a lock."
http://www.mikeash.com/pyblog/friday-qa-2009-07-10-type-specifiers-in-c-part-3.html

So, what is the contract about atomicity of assignments/reads of a variable? Are there any documents,references from Apple?

Thanks

eschatz at 2013-11-28 11:15:41:
Hi Mike,

It's me again.
You say that Martin Schuerrer's swizzling version is fine but how do we sure that method_exchangeImplementations is thread-safe with any message call to the method to be swizzled? Would not it be possible that another thread could see half modified pointer to the method and crash?

Thanks


Comments RSS feed for this page

Add your thoughts, post a comment:

Spam and off-topic posts will be deleted without notice. Culprits may be publicly humiliated at my sole discretion.

Name:
Web site:
Comment:
Formatting: <i> <b> <blockquote> <code>. URLs are automatically hyperlinked.
Code syntax highlighting thanks to Pygments.
Hosted at DigitalOcean.