From 75cd2405924bae4e378a8ab74d0a03c00351f937 Mon Sep 17 00:00:00 2001 From: "gtm.daemon" Date: Mon, 13 Aug 2012 21:30:12 +0000 Subject: [Author: grobbins] Modernize GTMObjectSingleton: Use dispatch_once, make ARC compatible, remove non-allocation NSObject methods, remove dependence on GTMDevAssert, add link to Chris Hanson's discussion of singletons, add comment discouraging developers from using this header file. R=thomasvl APPROVED=thomasvl DELTA=75 (24 added, 39 deleted, 12 changed) --- Foundation/GTMObjectSingleton.h | 87 +++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 51 deletions(-) (limited to 'Foundation') diff --git a/Foundation/GTMObjectSingleton.h b/Foundation/GTMObjectSingleton.h index fe1cc75..eeb9ec7 100644 --- a/Foundation/GTMObjectSingleton.h +++ b/Foundation/GTMObjectSingleton.h @@ -1,6 +1,6 @@ // // GTMObjectSingleton.h -// Macro to implement methods for a singleton +// Macro to implement a creation method for a singleton // // Copyright 2005-2008 Google Inc. // @@ -17,56 +17,41 @@ // the License. // -#import "GTMDefines.h" - -/// This macro implements the various methods needed to make a safe singleton. // -/// This Singleton pattern was taken from: -/// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html -/// -/// Sample usage: -/// -/// GTMOBJECT_SINGLETON_BOILERPLATE(SomeUsefulManager, sharedSomeUsefulManager) -/// (with no trailing semicolon) -/// +// This file is still around for compatibility with apps relying on its macro, +// but given how simple this is, there is not a compelling reason for any app to +// use this macro. +// +// For a reasonable discussion of Objective-C singletons, see +// http://eschatologist.net/blog/?p=178 +// +// Sample usage: +// +// GTMOBJECT_SINGLETON_BOILERPLATE(SomeUsefulManager, sharedSomeUsefulManager) +// (with no trailing semicolon) +// + +#if NS_BLOCKS_AVAILABLE + +#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_) \ ++ (_object_name_ *)_shared_obj_name_ { \ + static _object_name_ *obj; \ + static dispatch_once_t onceToken; \ + dispatch_once(&onceToken, ^{ \ + obj = [[self alloc] init]; \ + }); \ + return obj; \ +} + +#else + #define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_) \ -static _object_name_ *z##_shared_obj_name_ = nil; \ -+ (_object_name_ *)_shared_obj_name_ { \ - @synchronized(self) { \ - if (z##_shared_obj_name_ == nil) { \ - /* Note that 'self' may not be the same as _object_name_ */ \ - /* first assignment done in allocWithZone but we must reassign in case init fails */ \ - z##_shared_obj_name_ = [[self alloc] init]; \ - _GTMDevAssert((z##_shared_obj_name_ != nil), @"didn't catch singleton allocation"); \ - } \ - } \ - return z##_shared_obj_name_; \ -} \ -+ (id)allocWithZone:(NSZone *)zone { \ - @synchronized(self) { \ - if (z##_shared_obj_name_ == nil) { \ - z##_shared_obj_name_ = [super allocWithZone:zone]; \ - return z##_shared_obj_name_; \ - } \ - } \ - \ - /* We can't return the shared instance, because it's been init'd */ \ - _GTMDevAssert(NO, @"use the singleton API, not alloc+init"); \ - return nil; \ -} \ -- (id)retain { \ - return self; \ -} \ -- (NSUInteger)retainCount { \ - return NSUIntegerMax; \ -} \ -- (oneway void)release { \ -} \ -- (id)autorelease { \ - return self; \ -} \ -- (id)copyWithZone:(NSZone *)zone { \ - GTM_UNUSED(zone); \ - return self; \ -} \ ++ (_object_name_ *)_shared_obj_name_ { \ + static _object_name_ *obj; \ + if (obj == nil) { \ + obj = [[self alloc] init]; \ + } \ + return obj; \ +} +#endif // NS_BLOCKS_AVAILABLE -- cgit v1.2.3