-
-
Save janodev/4739849 to your computer and use it in GitHub Desktop.
dispatch_once is not reentrant. Use a NSReentrantLock if you want reentrancy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CC=clang | |
CFLAGS+=-std=c99 -g | |
LDFLAGS+=-framework Foundation | |
dispatch_once_reentrancy_test: dispatch_once_reentrancy_test.o |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.