TM iOS: reduce the scope of cache access lock

Summary: We just need to protect access to the cache, we don't need to protect the entire module lookup, because a module initialization may try to lookup another module, causing deadlocks.

Reviewed By: RSNara

Differential Revision: D15690645

fbshipit-source-id: cbb780db8699a94f2c9a2e121b35ddad2b125b65
This commit is contained in:
Kevin Gozali
2019-06-06 09:40:21 -07:00
committed by Facebook Github Bot
parent 9b61896f40
commit 360e999937
@@ -211,37 +211,46 @@ static Class getFallbackClassFromName(const char *name)
*/
- (id<RCTTurboModule>)provideRCTTurboModule:(const char *)moduleName
{
std::lock_guard<std::mutex> guard{_rctTurboModuleCacheLock};
auto rctTurboModuleCacheLookup = _rctTurboModuleCache.find(moduleName);
if (rctTurboModuleCacheLookup != _rctTurboModuleCache.end()) {
return rctTurboModuleCacheLookup->second;
}
/**
* Step 2a: Resolve platform-specific class.
*/
Class moduleClass;
if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
moduleClass = [_delegate getModuleClassFromName:moduleName];
}
if (!moduleClass) {
moduleClass = getFallbackClassFromName(moduleName);
}
if (![moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) {
return nil;
}
/**
* Step 2b: Ask hosting application/delegate to instantiate this class
*/
id<RCTTurboModule> module = nil;
if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
module = [_delegate getModuleInstanceFromClass:moduleClass];
} else {
module = [moduleClass new];
{
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
auto rctTurboModuleCacheLookup = _rctTurboModuleCache.find(moduleName);
if (rctTurboModuleCacheLookup != _rctTurboModuleCache.end()) {
return rctTurboModuleCacheLookup->second;
}
/**
* Step 2a: Resolve platform-specific class.
*/
if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
moduleClass = [_delegate getModuleClassFromName:moduleName];
}
if (!moduleClass) {
moduleClass = getFallbackClassFromName(moduleName);
}
if (![moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) {
return nil;
}
/**
* Step 2b: Ask hosting application/delegate to instantiate this class
*/
if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
module = [_delegate getModuleInstanceFromClass:moduleClass];
} else {
module = [moduleClass new];
}
if ([module respondsToSelector:@selector(setTurboModuleLookupDelegate:)]) {
[module setTurboModuleLookupDelegate:self];
}
_rctTurboModuleCache.insert({moduleName, module});
}
/**
@@ -280,12 +289,6 @@ static Class getFallbackClassFromName(const char *name)
}
}
if ([module respondsToSelector:@selector(setTurboModuleLookupDelegate:)]) {
[module setTurboModuleLookupDelegate:self];
}
_rctTurboModuleCache.insert({moduleName, module});
/**
* Broadcast that this TurboModule was created.
*
@@ -336,6 +339,7 @@ static Class getFallbackClassFromName(const char *name)
- (BOOL)moduleIsInitialized:(const char *)moduleName
{
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
return _rctTurboModuleCache.find(std::string(moduleName)) != _rctTurboModuleCache.end();
}