use shared mutex in RCTSurfacePresenter

Summary:
Otherwise reloading from metro deadlocks like this:
`[RCTSurfaceRegistry _stopAllSurfaces]` is calling `[RCTSurfaceRegistry enumerateWithBlock]` which locks `_mutex` and then we call `surfaceForRootTag` which then deadlocks on the same mutex:
https://pxl.cl/tmm1

Reviewed By: shergin

Differential Revision: D14679843

fbshipit-source-id: 9f4ecdfa7a79fcf7f3fc2ce437d4399b00910f26
This commit is contained in:
Spencer Ahrens
2019-03-29 10:27:20 -07:00
committed by Facebook Github Bot
parent b88cc7bf52
commit 366fa2f1ef

View File

@@ -8,11 +8,15 @@
#import "RCTSurfaceRegistry.h"
#import <mutex>
#import <shared_mutex>
#import <better/mutex.h>
#import <React/RCTFabricSurface.h>
using namespace facebook;
@implementation RCTSurfaceRegistry {
std::mutex _mutex;
better::shared_mutex _mutex;
NSMapTable<id, RCTFabricSurface *> *_registry;
}
@@ -28,13 +32,13 @@
- (void)enumerateWithBlock:(RCTSurfaceEnumeratorBlock)block
{
std::lock_guard<std::mutex> lock(_mutex);
std::shared_lock<better::shared_mutex> lock(_mutex);
block([_registry objectEnumerator]);
}
- (void)registerSurface:(RCTFabricSurface *)surface
{
std::lock_guard<std::mutex> lock(_mutex);
std::unique_lock<better::shared_mutex> lock(_mutex);
ReactTag rootTag = surface.rootViewTag.integerValue;
[_registry setObject:surface forKey:(__bridge id)(void *)rootTag];
@@ -42,7 +46,7 @@
- (void)unregisterSurface:(RCTFabricSurface *)surface
{
std::lock_guard<std::mutex> lock(_mutex);
std::unique_lock<better::shared_mutex> lock(_mutex);
ReactTag rootTag = surface.rootViewTag.integerValue;
[_registry removeObjectForKey:(__bridge id)(void *)rootTag];
@@ -50,7 +54,7 @@
- (RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag
{
std::lock_guard<std::mutex> lock(_mutex);
std::shared_lock<better::shared_mutex> lock(_mutex);
return [_registry objectForKey:(__bridge id)(void *)rootTag];
}