Skip to content

Instantly share code, notes, and snippets.

@MadCoder
Last active June 23, 2016 04:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MadCoder/d33634fb28f1ed3c9d480f1887502320 to your computer and use it in GitHub Desktop.
Save MadCoder/d33634fb28f1ed3c9d480f1887502320 to your computer and use it in GitHub Desktop.
@implementation MyClass
+ (instancetype)sharedInstanceWithError:(NSError **)error
{
static _Atomic(MyClass *) sMyClass;
MyClass *tmp = nil, *expected = nil;
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
// this assumes that this platform has consume ordering
// for loads through dereferencing pointers, which both intel & arm have.
tmp = atomic_load_explicit(&sMyClass, memory_order_relaxed);
#else
// platforms where this isn't true need an acquire barrier
tmp = atomic_load_explicit(&sMyClass, memory_order_acquire);
#endif
if (tmp) {
return tmp;
}
// /!\ /!\ /!\ ACHTUNG MINEN /!\ /!\ /!\
// for this whole trick to work, [[MyClass alloc] init] should not do any
// store to memory that will not be read from an expression derived from
// `sMyClass` without adding extra synchronization
//
// It also assumes that it's okay to create and try to setup several
// of these objects which isn't always the case
tmp = [[MyClass alloc] init];
if (![tmp setupWithError:error]) {
return nil;
}
// try to publish our init, but we may lose that race
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__arm64__)
if (atomic_compare_exchange_strong_explicit(&sMyClass, &expected,
tmp, memory_order_release, memory_order_relaxed)) {
// we won the init race
return tmp;
}
#else
if (atomic_compare_exchange_strong(&sMyClass, &expected, tmp)) {
// we won the init race
return tmp;
}
#endif
// we failed the init race, kill our instance
[tmp release];
// return current value
return expected;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment