Tag Archives: Xcode

Double-Checked Locking and Objective-C

A common problem in software is to do something exactly once – e.g. create a singleton.  A corollary of that action is to do something exactly once in the life of an instance.  I have found myself using the corollary much more frequently as I move away from using singletons, which I’ve done to improve testability.

With singletons, a common solution is to use locking or, to avoid the performance penalty of locking, double-checked locking.  Of course, double-checked locking has issues with most modern languages caused by CPU and compiler instruction reordering.  Objective-C has provided an elegant solution to those problems, but the solution comes up a little bit short.

Creating a Singleton – Single-Threaded

In a single -threaded application, creating a singleton can be done without additional protection, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        s_sharedInstance = [MyClass new];
    }

    return s_sharedInstance;
}

Creating a Singleton – Multi-Threaded

In a multi-threaded application, it’s not so simple as you will want to protect yourself against multiple callers of this method.  A simple solution simply adds a lock:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    @synchronized(self)
    {
        if (s_sharedInstance == nil)
        {
            s_sharedInstance = [MyClass new];
        }
    }

    return s_sharedInstance;
}

The problem with this solution is that you pay the price of locking even though you only need it the first time the method is called.

Double-Checked Locking

A common solution to avoid the penalty of locking is to use double-checked locking.  With double-checked locking you check the value of the static instance both outside and inside the lock, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                s_sharedInstance = [MyClass new];
            }
        }
    }

    return s_sharedInstance;
}

At first blush, it would seem that this would solve the problem of assigning the static variable AND avoiding the penalty of the lock.  The problem is that the CPU and/or the compiler could reorder the memory access instructions.  A solution suggested by Mike Ash inserts memory barriers before accessing the variable and uses the volatile keyword.  The memory barrier, available in libkern/OSAtomic.h, solves the CPU problem and the volatile keyword solves the compiler problem.

+ (MyClass *) sharedInstance
{
    static MyClass * volatile s_sharedInstance = nil;
    if (s_sharedInstance == nil)
    {
        @synchronized(self)
        {
            if (s_sharedInstance == nil)
            {
                OSMemoryBarrier();
                s_sharedInstance = [MyClass new];
            }
        }
    }

    OSMemoryBarrier();
    return s_sharedInstance;
}

The problem with this solution is that it is still quite expensive in the most common case.  Apple has provided another solution:  dispatch_once.

dispatch_once

dispatch_once is provided with Grand Central Dispatch to execute statements exactly once, like this:

+ (MyClass *) sharedInstance
{
    static MyClass * s_sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_sharedInstance = [MyClass new];
    });

    return s_sharedInstance
}

This is a terrific solution for use with singletons, but what if you want to use it with an instance?  It actually happens to work, but Apple has a warning against using it in this way in the documentation for dispatch_once:

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.

Hmm, that’s unfortunate.  Here’s hoping Apple will change their implementation.  In the meantime, it would appear that the only solutions for the non-static and non-global case are:

  1. Use a synchronized block for every call.
  2. Use memory barriers.

References

Folding code in Xcode

A colleague of mine has the practice of collapsing all the methods in an Objective C file when he loads it to simplify finding the right method to view. When I asked him how he did it, he couldn’t remember since it was an automatic action. I finally got around to figuring out how to do it.

The feature is called Code Folding and can be done using the pointer, the menu bar, and the keyboard.

Code Folding using the Pointer

You may have noticed the different colored gray bars on the left of your code in Xcode and may have even accidentally hovered over one of them and been treated to a drastic change in the UI. Those gray bars allow you to fold – or collapse – your code. Using those bars, you can fold any size block, such as an if block, a for block, an @synchronized block, or even a whole method block.

Hovering over the gray bar shows you the block that will be folded. Clicking on the gray bar folds the block and shows a yellow ellipsis between the curly braces where the block used to be. It also changes the gray bar to an arrow. Clicking the arrow or double-clicking the ellipsis will unfold – or expand – the folded block.

Code Folding using the Menu Bar

The code folding functionality is exposed in the menus accessible from the menu bar as well.  In Xcode 4, check out Editor -> Code Folding.

Code Folding using the Keyboard

Apple has defined default keystrokes for code folding, but I found that some of them conflicted with keystrokes defined for other functions. In most cases the conflicts were caused by changes I had made – either in Xcode or in Mac OS X Lion – to accommodate writing code.

The following code folding functionality can be controlled using the keyboard:

  1. Fold all methods and functions – Option + Cmd + Shift + Left Arrow
  2. Unfold all methods and functions – Option + Cmd + Shift + Right Arrow
  3. Fold the current block – Option + Cmd + Left Arrow
  4. Unfold the current block – Option + Cmd + Right Arrow

I had to change the fold/unfold block key bindings because they conflicted with the key bindings I had selected for switching between Spaces in Lion. I changed them to Ctrl + Cmd + Shift + Left Arrow/Right Arrow respectively. This, of course, required that I change another key binding in Xcode – the key bindings for fold/unfold comment blocks.

Comment blocks are blocks of comments using /* and */ as delimiters. Since I almost never use this style of commenting, removing the key binding for folding/unfolding comment blocks in favor of code folding/unfolding was a good trade-off for me.