Objective-C でsingleton pattern
Objective-Cではマルチスレッドでも安全にsingleton objectを初期化するための dispatch_once() というのが使えるようだけど、double-checked lockingは多少効果があるようだ。
ただ最近の gcc/clangはデフォルトで -fthreadsafe-statics が有効なので Objective C++ だと dispatch_once() すら使うことなく安全に初期化できるはずで、無用なhackかもしれない。要検証。
#import <ctime> #import <Foundation/Foundation.h> // simple ver. NSString* getInstance1() { static dispatch_once_t guard; static NSString* instance = nil; dispatch_once(&guard, ^{ instance = @"foo"; }); return instance; } // double-checked locking ver. NSString* getInstance2() { static dispatch_once_t guard; static NSString* instance = nil; if (! instance) { dispatch_once(&guard, ^{ instance = @"foo"; }); } return instance; } int main() { { auto t0 = std::clock(); NSString* s = nil; for (auto i = 0; i < 1000000000; ++i) { s = getInstance1(); } NSLog(@"1 (%p) elapsed: %lu", s, std::clock() - t0); } { auto t0 = std::clock(); NSString* s = nil; for (auto i = 0; i < 1000000000; ++i) { s = getInstance2(); } NSLog(@"2 (%p) elapsed: %lu", s, std::clock() - t0); } return 0; }
結果:
$ clang++ -framework Foundation -std=c++0x dispatch_once.mm $ ./a.out 2012-08-15 09:17:54.689 a.out[69021:707] 1 (0x107074060) elapsed: 4328046 2012-08-15 09:17:57.832 a.out[69021:707] 2 (0x107074060) elapsed: 3140014