Fabric: Scheduler-specific dependencies were moved to a separate class from ContextContainer

Summary: ContextContainer should contain only product/component-specific dependencies and stay unchanged during VM/Scheduler reloading.

Reviewed By: JoshuaGross

Differential Revision: D15636656

fbshipit-source-id: fe5de1b6c92f659b28d31eba901c04c5b23fe1d1
This commit is contained in:
Valentin Shergin
2019-06-07 12:03:57 -07:00
committed by Facebook Github Bot
parent 63ed75fe9e
commit a19cfc2273
8 changed files with 108 additions and 56 deletions
+2 -2
View File
@@ -14,6 +14,7 @@
#import <react/core/LayoutContext.h>
#import <react/mounting/MountingCoordinator.h>
#import <react/uimanager/ComponentDescriptorFactory.h>
#import <react/uimanager/SchedulerToolbox.h>
#import <react/utils/ContextContainer.h>
NS_ASSUME_NONNULL_BEGIN
@@ -36,8 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (atomic, weak, nullable) id<RCTSchedulerDelegate> delegate;
- (instancetype)initWithContextContainer:(facebook::react::ContextContainer::Shared)contextContatiner
componentRegistryFactory:(facebook::react::ComponentRegistryFactory)componentRegistryFactory;
- (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox;
- (void)startSurfaceWithSurfaceId:(facebook::react::SurfaceId)surfaceId
moduleName:(NSString *)moduleName
+2 -3
View File
@@ -43,12 +43,11 @@ class SchedulerDelegateProxy : public SchedulerDelegate {
std::shared_ptr<SchedulerDelegateProxy> _delegateProxy;
}
- (instancetype)initWithContextContainer:(ContextContainer::Shared)contextContainer
componentRegistryFactory:(ComponentRegistryFactory)componentRegistryFactory
- (instancetype)initWithToolbox:(facebook::react::SchedulerToolbox)toolbox
{
if (self = [super init]) {
_delegateProxy = std::make_shared<SchedulerDelegateProxy>((__bridge void *)self);
_scheduler = std::make_shared<Scheduler>(contextContainer, componentRegistryFactory);
_scheduler = std::make_shared<Scheduler>(toolbox);
_scheduler->setDelegate(_delegateProxy.get());
}
+33 -24
View File
@@ -31,6 +31,7 @@
#import <react/core/LayoutConstraints.h>
#import <react/core/LayoutContext.h>
#import <react/uimanager/ComponentDescriptorFactory.h>
#import <react/uimanager/SchedulerToolbox.h>
#import <react/utils/ContextContainer.h>
#import <react/utils/ManagedObjectWrapper.h>
@@ -203,8 +204,22 @@ using namespace facebook::react;
createComponentDescriptorRegistryWithParameters:{eventDispatcher, contextContainer}];
};
_scheduler = [[RCTScheduler alloc] initWithContextContainer:self.contextContainer
componentRegistryFactory:componentRegistryFactory];
auto runtimeExecutor = [self _runtimeExecutor];
auto toolbox = SchedulerToolbox{};
toolbox.contextContainer = _contextContainer;
toolbox.componentRegistryFactory = componentRegistryFactory;
toolbox.runtimeExecutor = runtimeExecutor;
toolbox.synchronousEventBeatFactory = [runtimeExecutor]() {
return std::make_unique<MainRunLoopEventBeat>(runtimeExecutor);
};
toolbox.asynchronousEventBeatFactory = [runtimeExecutor]() {
return std::make_unique<RuntimeEventBeat>(runtimeExecutor);
};
_scheduler = [[RCTScheduler alloc] initWithToolbox:toolbox];
_scheduler.delegate = self;
return _scheduler;
@@ -212,18 +227,8 @@ using namespace facebook::react;
@synthesize contextContainer = _contextContainer;
- (ContextContainer::Shared)contextContainer
- (RuntimeExecutor)_runtimeExecutor
{
std::lock_guard<std::mutex> lock(_contextContainerMutex);
if (_contextContainer) {
return _contextContainer;
}
_contextContainer = std::make_shared<ContextContainer>();
_contextContainer->registerInstance(_reactNativeConfig, "ReactNativeConfig");
auto messageQueueThread = _batchedBridge.jsMessageThread;
if (messageQueueThread) {
// Make sure initializeBridge completed
@@ -239,20 +244,25 @@ using namespace facebook::react;
[((RCTCxxBridge *)_batchedBridge) invokeAsync:[runtime, callback = std::move(callback)]() { callback(*runtime); }];
};
EventBeatFactory synchronousBeatFactory = [runtimeExecutor]() {
return std::make_unique<MainRunLoopEventBeat>(runtimeExecutor);
};
return runtimeExecutor;
}
EventBeatFactory asynchronousBeatFactory = [runtimeExecutor]() {
return std::make_unique<RuntimeEventBeat>(runtimeExecutor);
};
- (ContextContainer::Shared)contextContainer
{
std::lock_guard<std::mutex> lock(_contextContainerMutex);
_contextContainer->registerInstance<EventBeatFactory>(synchronousBeatFactory, "synchronous");
_contextContainer->registerInstance<EventBeatFactory>(asynchronousBeatFactory, "asynchronous");
_contextContainer->registerInstance(runtimeExecutor, "runtime-executor");
if (_contextContainer) {
return _contextContainer;
}
_contextContainer = std::make_shared<ContextContainer>();
// Please do not add stuff here; `SurfacePresenter` must not alter `ContextContainer`.
// Those two pieces eventually should be moved out there:
// * `RCTImageLoader` should be moved to `RNImageComponentView`.
// * `ReactNativeConfig` should be set by outside product code.
_contextContainer->registerInstance(_reactNativeConfig, "ReactNativeConfig");
_contextContainer->registerInstance(wrapManagedObject([_bridge imageLoader]), "RCTImageLoader");
return _contextContainer;
}
@@ -390,7 +400,6 @@ using namespace facebook::react;
{
std::lock_guard<std::mutex> lock(_schedulerMutex);
_scheduler = nil;
_contextContainer = nil;
}
}
@@ -18,6 +18,7 @@
#include <react/uimanager/ComponentDescriptorFactory.h>
#include <react/uimanager/Scheduler.h>
#include <react/uimanager/SchedulerDelegate.h>
#include <react/uimanager/SchedulerToolbox.h>
#include <react/uimanager/primitives.h>
#include <react/utils/ContextContainer.h>
#include <react/utils/TimeUtils.h>
@@ -136,16 +137,15 @@ void Binding::installFabricUIManager(
std::shared_ptr<const ReactNativeConfig> config =
std::make_shared<const ReactNativeConfigHolder>(reactNativeConfig);
contextContainer->registerInstance(config, "ReactNativeConfig");
contextContainer->registerInstance<EventBeatFactory>(
synchronousBeatFactory, "synchronous");
contextContainer->registerInstance<EventBeatFactory>(
asynchronousBeatFactory, "asynchronous");
contextContainer->registerInstance(javaUIManager_, "FabricUIManager");
contextContainer->registerInstance(runtimeExecutor, "runtime-executor");
scheduler_ = std::make_shared<Scheduler>(
contextContainer, componentsRegistry->buildRegistryFunction);
auto toolbox = SchedulerToolbox{};
toolbox.contextContainer = contextContainer;
toolbox.componentRegistryFactory = componentsRegistry->buildRegistryFunction;
toolbox.runtimeExecutor = runtimeExecutor;
toolbox.synchronousEventBeatFactory = synchronousBeatFactory;
toolbox.asynchronousEventBeatFactory = asynchronousBeatFactory;
scheduler_ = std::make_shared<Scheduler>(toolbox);
scheduler_->setDelegate(this);
}
+8 -16
View File
@@ -18,19 +18,11 @@
namespace facebook {
namespace react {
Scheduler::Scheduler(
ContextContainer::Shared const &contextContainer,
ComponentRegistryFactory buildRegistryFunction) {
const auto asynchronousEventBeatFactory =
contextContainer->getInstance<EventBeatFactory>("asynchronous");
const auto synchronousEventBeatFactory =
contextContainer->getInstance<EventBeatFactory>("synchronous");
runtimeExecutor_ =
contextContainer->getInstance<RuntimeExecutor>("runtime-executor");
Scheduler::Scheduler(SchedulerToolbox schedulerToolbox) {
runtimeExecutor_ = schedulerToolbox.runtimeExecutor;
reactNativeConfig_ =
contextContainer->getInstance<std::shared_ptr<const ReactNativeConfig>>(
schedulerToolbox.contextContainer->getInstance<std::shared_ptr<const ReactNativeConfig>>(
"ReactNativeConfig");
auto uiManager = std::make_unique<UIManager>();
@@ -55,11 +47,11 @@ Scheduler::Scheduler(
auto eventDispatcher = std::make_shared<EventDispatcher>(
eventPipe,
statePipe,
synchronousEventBeatFactory,
asynchronousEventBeatFactory);
schedulerToolbox.synchronousEventBeatFactory,
schedulerToolbox.asynchronousEventBeatFactory);
componentDescriptorRegistry_ =
buildRegistryFunction(eventDispatcher, contextContainer);
componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory(
eventDispatcher, schedulerToolbox.contextContainer);
rootComponentDescriptor_ =
std::make_unique<const RootComponentDescriptor>(eventDispatcher);
@@ -72,7 +64,7 @@ Scheduler::Scheduler(
UIManagerBinding::install(runtime, uiManagerBinding_);
});
contextContainer->registerInstance(
schedulerToolbox.contextContainer->registerInstance(
std::weak_ptr<ComponentDescriptorRegistry const>(
componentDescriptorRegistry_),
"ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE");
+2 -3
View File
@@ -18,6 +18,7 @@
#include <react/uimanager/ComponentDescriptorFactory.h>
#include <react/uimanager/ComponentDescriptorRegistry.h>
#include <react/uimanager/SchedulerDelegate.h>
#include <react/uimanager/SchedulerToolbox.h>
#include <react/uimanager/UIManagerBinding.h>
#include <react/uimanager/UIManagerDelegate.h>
#include <react/uimanager/primitives.h>
@@ -31,9 +32,7 @@ namespace react {
*/
class Scheduler final : public UIManagerDelegate, public ShadowTreeDelegate {
public:
Scheduler(
ContextContainer::Shared const &contextContainer,
ComponentRegistryFactory buildRegistryFunction);
Scheduler(SchedulerToolbox schedulerToolbox);
~Scheduler();
#pragma mark - Surface Management
@@ -0,0 +1,6 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
#include "SchedulerToolbox.h"
@@ -0,0 +1,47 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
#pragma once
#include <react/core/EventBeat.h>
#include <react/uimanager/ComponentDescriptorFactory.h>
#include <react/uimanager/primitives.h>
#include <react/utils/ContextContainer.h>
namespace facebook {
namespace react {
/*
* Contains all external dependencies of Scheduler.
* Copyable.
*/
struct SchedulerToolbox final {
/*
* Represents general purpose DI container for product components/needs.
* Must not be `nullptr`.
*/
ContextContainer::Shared contextContainer;
/*
* Represents externally managed, lazily available collection of components.
*/
ComponentRegistryFactory componentRegistryFactory;
/*
* Represents running JavaScript VM and associated execution queue.
*/
RuntimeExecutor runtimeExecutor;
/*
* Asynchronous & synchronous event beats.
* Represent connections with the platform-specific run loops and general
* purpose background queue.
*/
EventBeatFactory asynchronousEventBeatFactory;
EventBeatFactory synchronousEventBeatFactory;
};
} // namespace react
} // namespace facebook