mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Invalidate TurboModules on their method queues
Summary: ## Rationale With the bridge, the invalidate method of every TurboModule gets called on the TurboModule's method queue. This ensures that we can safely clean up resources accessed in the TurboModule's async methods. In bridgeless mode, we don't invalidate each module on its method queue. After this diff, we will clean up every TurboModule on its own method queue. ## Changes - Make RCTInstance dealloc itself on the JavaScript thread. - Terminate the JavaScript thread on the JavaScript thread. This ensures that no work executes on the JavaScript thread after we clean up RCTInstance. - Make [RCTTurboModuleManager invalidate] execute right before RCTInstance terminates the JavaScript thread. - **Fix:** Make [RCTTurboModuleManger invalidate] synchronously invalidate modules on their own method queues. Changelog: [Internal] Reviewed By: PeteTheHeat Differential Revision: D27933587 fbshipit-source-id: 7630e7fc074df2f5a3293192431105c747b8588f
This commit is contained in:
1 parent
090196f330
commit
f34a2899e4
1 file changed
+39
-34
@@ -834,6 +834,27 @@ static Class getFallbackClassFromName(const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
[self _enterInvalidatingState];
|
||||
}
|
||||
|
||||
- (void)bridgeDidInvalidateModules:(NSNotification *)notification
|
||||
{
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
if (bridge != _bridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self _invalidateModules];
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self _enterInvalidatingState];
|
||||
[self _invalidateModules];
|
||||
}
|
||||
|
||||
- (void)_enterInvalidatingState
|
||||
{
|
||||
// This should halt all insertions into _turboModuleHolders
|
||||
if (RCTTurboModuleSharedMutexInitEnabled()) {
|
||||
std::unique_lock<std::shared_timed_mutex> guard(_turboModuleHoldersSharedMutex);
|
||||
@@ -844,13 +865,8 @@ static Class getFallbackClassFromName(const char *name)
|
||||
}
|
||||
}
|
||||
|
||||
- (void)bridgeDidInvalidateModules:(NSNotification *)notification
|
||||
- (void)_invalidateModules
|
||||
{
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
if (bridge != _bridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Backward-compatibility: RCTInvalidating handling.
|
||||
dispatch_group_t moduleInvalidationGroup = dispatch_group_create();
|
||||
|
||||
@@ -870,17 +886,28 @@ static Class getFallbackClassFromName(const char *name)
|
||||
if ([module respondsToSelector:@selector(invalidate)]) {
|
||||
if ([module respondsToSelector:@selector(methodQueue)]) {
|
||||
dispatch_queue_t methodQueue = [module performSelector:@selector(methodQueue)];
|
||||
|
||||
if (methodQueue) {
|
||||
dispatch_group_enter(moduleInvalidationGroup);
|
||||
[bridge
|
||||
dispatchBlock:^{
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
dispatch_group_leave(moduleInvalidationGroup);
|
||||
}
|
||||
queue:methodQueue];
|
||||
dispatch_block_t invalidateModule = ^{
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
dispatch_group_leave(moduleInvalidationGroup);
|
||||
};
|
||||
|
||||
if (_bridge) {
|
||||
[_bridge dispatchBlock:invalidateModule queue:methodQueue];
|
||||
} else {
|
||||
// Bridgeless mode
|
||||
if (methodQueue == RCTJSThread) {
|
||||
invalidateModule();
|
||||
} else {
|
||||
dispatch_async(methodQueue, invalidateModule);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
}
|
||||
}
|
||||
@@ -893,26 +920,4 @@ static Class getFallbackClassFromName(const char *name)
|
||||
_turboModuleCache.clear();
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
if (RCTTurboModuleSharedMutexInitEnabled()) {
|
||||
std::unique_lock<std::shared_timed_mutex> guard(_turboModuleHoldersSharedMutex);
|
||||
_invalidating = true;
|
||||
} else {
|
||||
std::lock_guard<std::mutex> guard(_turboModuleHoldersMutex);
|
||||
_invalidating = true;
|
||||
}
|
||||
|
||||
// Backward-compatibility: RCTInvalidating handling, but not adhering to desired methodQueue.
|
||||
for (const auto &p : _turboModuleHolders) {
|
||||
id<RCTTurboModule> module = p.second.getModule();
|
||||
if ([module respondsToSelector:@selector(invalidate)]) {
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
_turboModuleHolders.clear();
|
||||
_turboModuleCache.clear();
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user