Skip to content

Instantly share code, notes, and snippets.

@janodev
Forked from boredzo/Makefile
Last active September 23, 2016 19:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janodev/4739849 to your computer and use it in GitHub Desktop.
Save janodev/4739849 to your computer and use it in GitHub Desktop.
dispatch_once is not reentrant. Use a NSReentrantLock if you want reentrancy.
#import <Foundation/Foundation.h>
static NSRecursiveLock *_lock = nil;
// constructor = run before main. used = emit code even if the function is not referenced.
// See http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
static void runBeforeMain(void) __attribute__ ((constructor, used));
static void runBeforeMain(void) {
_lock = [NSRecursiveLock new];
}
static void test(void)
{
static NSUInteger count = 0;
NSLog(@"iteration #%lu", ++count);
// YES = deadlock after a reentrant call using dispatch_once
// NO = allow reentrant calls using NSRecursiveLock
BOOL deadlock = YES;
if (deadlock){
static dispatch_once_t token;
dispatch_once(&token, ^{
test();
});
} else {
[_lock lock];
test();
[_lock unlock];
}
count--;
}
int main(int argc, char **argv) {
@autoreleasepool {
test();
}
return EXIT_SUCCESS;
}
CC=clang
CFLAGS+=-std=c99 -g
LDFLAGS+=-framework Foundation
dispatch_once_reentrancy_test: dispatch_once_reentrancy_test.o
@lemonkey
Copy link

Does this address the issue with using @synchronized(self) within a singleton while code elsewhere could also being using @synchronized(singleton_instance), causing a dead lock?

While dispatch_once doesn't have this problem, like you mention it is not reentrant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment