advantis
9/26/2012 - 12:51 PM

Retrospective of Singleton pattern in Cocoa

Retrospective of Singleton pattern in Cocoa

// Simple implementation (not thread-safe)
+ (Singleton *) sharedSingleton
{
    static Singleton *instance;
    if (nil == instance)
    {
        instance = [self new];
    }
    return instance;
}

// Using @synchronized directive (overhead on every call)
+ (Singleton *) sharedSingleton
{
    static Singleton *instance;
    @synchronized (self)
    {
        if (nil == instance)
        {
            instance = [self new];
        }
    }
    return instance;
}

// Using Double-Checked Locking pattern (not really safe, depends on compiler)
// See http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
+ (Singleton *) sharedSingleton
{
    static Singleton * volatile instance;

    if (nil == instance)
    {
        @synchronized (self)
        {
            if (nil == instance)
            {
                instance = [self new];
            }
        }
    }
    return instance;
}

// Using OS-specific atomic operations (possible temporary creation of two instances)
+ (Singleton *) sharedSingleton
{
    static Singleton * volatile instance;                                                
                                                                    
    while (nil == instance)
    {                                                                          
        Singleton *temp = [self new];                                                                 
        if (!OSAtomicCompareAndSwapPtrBarrier(0x0, temp, &instance))
        {
            [temp release];                                                                                   
        }                                                                                                    
    }                                                                                                        
    return instance;                                                                        
}

// Using the “Method Swizzling” technique (impact on superclases implementation)
static Singleton *instance;

+ (Singleton *) sharedSingleton
{
    @synchronized(self)
    {
        if (nil == instance)
        {
            instance = [self new];
            Method origMethod = class_getClassMethod(self, _cmd);
            Method newMethod = class_getClassMethod(self, @selector(someMethod));
            method_exchangeImplementations(origMethod, newMethod);
        }
    }
    return instance;
}

+ (Singleton *) someMethod
{
    return instance;
}

// Using Grand Central Dispatch (only for iOS >= 4.0)
+ (Singleton *) sharedSingleton
{
    static Singleton *instance;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{ instance = [self new]; });
    return instance;
}

// Using Cocoa architecture (premature instantiation, impact on superclases implementation)
static Singleton *instance;

+ (void) initialize
{
    if ([Singleton class] == self)
    {
        instance = [self new];
    }
}

+ (Singleton *) sharedSingleton
{
    return instance;
}

// Using pthread
static Singleton *instance;
static void SingletonInit() { instance = [Singleton new]; }

+ (Singleton*) sharedSingleton
{
    static pthread_once_t once_control = PTHREAD_ONCE_INIT;
    pthread_once(&once_control, SingletonInit);
    return instance;
}