Fabric: Introducing Scheduler

Summary: Scheduler coordinates Shadow Tree updates and event flows (not yet).

Reviewed By: mdvacca

Differential Revision: D7503387

fbshipit-source-id: 4cb8bc574c25a0fd2ace6319c26c644a1e4757a9
This commit is contained in:
Valentin Shergin 2018-04-10 12:46:20 -07:00 committed by Facebook Github Bot
parent f6f7d0484c
commit ba45895a3f
3 changed files with 215 additions and 0 deletions

View File

@ -0,0 +1,108 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include "Scheduler.h"
#include <fabric/core/LayoutContext.h>
#include <fabric/uimanager/ComponentDescriptorRegistry.h>
#include <fabric/uimanager/FabricUIManager.h>
#include <fabric/view/ViewComponentDescriptor.h>
#include <fabric/view/ViewProps.h>
#include <fabric/view/ViewShadowNode.h>
#include "Differentiator.h"
namespace facebook {
namespace react {
Scheduler::Scheduler() {
auto componentDescriptorRegistry = std::make_shared<ComponentDescriptorRegistry>();
SharedComponentDescriptor viewComponentDescriptor = std::make_shared<ViewComponentDescriptor>();
componentDescriptorRegistry->registerComponentDescriptor(viewComponentDescriptor);
uiManager_ = std::make_shared<FabricUIManager>(componentDescriptorRegistry);
uiManager_->setDelegate(this);
}
Scheduler::~Scheduler() {
uiManager_->setDelegate(nullptr);
}
void Scheduler::registerRootTag(Tag rootTag) {
auto rootShadowNode = std::make_shared<RootShadowNode>(rootTag, rootTag, nullptr);
rootNodeRegistry_.insert({rootTag, rootShadowNode});
}
void Scheduler::unregisterRootTag(Tag rootTag) {
rootNodeRegistry_.erase(rootTag);
}
#pragma mark - Delegate
void Scheduler::setDelegate(SchedulerDelegate *delegate) {
delegate_ = delegate;
}
SchedulerDelegate *Scheduler::getDelegate() {
return delegate_;
}
#pragma mark - UIManagerDelegate
void Scheduler::uiManagerDidFinishTransaction(Tag rootTag, const SharedShadowNodeUnsharedList &rootChildNodes) {
SharedRootShadowNode oldRootShadowNode = rootNodeRegistry_[rootTag];
assert(oldRootShadowNode);
SharedRootShadowNode newRootShadowNode =
std::make_shared<RootShadowNode>(oldRootShadowNode, nullptr, SharedShadowNodeSharedList(rootChildNodes));
auto nonConstOldRootShadowNode = std::const_pointer_cast<RootShadowNode>(oldRootShadowNode);
auto nonConstNewRootShadowNode = std::const_pointer_cast<RootShadowNode>(newRootShadowNode);
LayoutContext layoutContext = LayoutContext();
layoutContext.affectedShadowNodes = std::make_shared<std::unordered_set<SharedLayoutableShadowNode>>();
LOG(INFO) << "Old Shadow Tree: \n" << oldRootShadowNode->getDebugDescription();
LOG(INFO) << "New Shadow Tree *before* layout: \n" << newRootShadowNode->getDebugDescription();
nonConstNewRootShadowNode->layout(layoutContext);
nonConstNewRootShadowNode->sealRecursive();
LOG(INFO) << "New Shadow Tree *after* layout: \n" << nonConstNewRootShadowNode->getDebugDescription();
TreeMutationInstructionList instructions = TreeMutationInstructionList();
calculateMutationInstructions(
instructions,
oldRootShadowNode,
oldRootShadowNode->ShadowNode::getChildren(),
newRootShadowNode->ShadowNode::getChildren()
);
LOG(INFO) << "TreeMutationInstructionList:";
for (auto instruction : instructions) {
LOG(INFO) << "Instruction: " << instruction.getDebugDescription();
}
rootNodeRegistry_[rootTag] = newRootShadowNode;
if (delegate_) {
delegate_->schedulerDidComputeMutationInstructions(rootTag, instructions);
}
}
void Scheduler::uiManagerDidCreateShadowNode(const SharedShadowNode &shadowNode) {
if (delegate_) {
delegate_->schedulerDidRequestPreliminaryViewAllocation(shadowNode->getComponentName());
}
}
#pragma mark - Deprecated
std::shared_ptr<FabricUIManager> Scheduler::getUIManager_DO_NOT_USE() {
return uiManager_;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,74 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <memory>
#include <fabric/core/ComponentDescriptor.h>
#include <fabric/core/LayoutConstraints.h>
#include <fabric/uimanager/SchedulerDelegate.h>
#include <fabric/uimanager/UIManagerDelegate.h>
#include <fabric/view/ViewShadowNode.h>
namespace facebook {
namespace react {
/*
* We expect having a dedicated subclass for root shadow node.
*/
using SharedRootShadowNode = SharedViewShadowNode;
using RootShadowNode = ViewShadowNode;
class FabricUIManager;
/*
* Scheduler coordinates Shadow Tree updates and event flows.
*/
class Scheduler:
public UIManagerDelegate {
public:
Scheduler();
~Scheduler();
#pragma mark - Root Nodes Managerment
void registerRootTag(Tag rootTag);
void unregisterRootTag(Tag rootTag);
void setLayoutConstraints(Tag rootTag, LayoutConstraints layoutConstraints);
#pragma mark - Delegate
/*
* Sets and gets the Scheduler's delegate.
* The delegate is stored as a raw pointer, so the owner must null
* the pointer before being destroyed.
*/
void setDelegate(SchedulerDelegate *delegate);
SchedulerDelegate *getDelegate();
#pragma mark - UIManagerDelegate
void uiManagerDidFinishTransaction(Tag rootTag, const SharedShadowNodeUnsharedList &rootChildNodes) override;
void uiManagerDidCreateShadowNode(const SharedShadowNode &shadowNode) override;
#pragma mark - Deprecated
/*
* UIManager instance must be temporarily exposed for registration purposes.
*/
std::shared_ptr<FabricUIManager> getUIManager_DO_NOT_USE();
private:
SchedulerDelegate *delegate_;
std::shared_ptr<FabricUIManager> uiManager_;
/*
* All commited `RootShadowNode` instances to differentiate against.
*/
std::unordered_map<Tag, SharedRootShadowNode> rootNodeRegistry_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,33 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#pragma once
#include <memory>
#include <fabric/core/ReactPrimitives.h>
#include <fabric/core/ShadowNode.h>
#include <fabric/uimanager/TreeMutationInstruction.h>
namespace facebook {
namespace react {
/*
* Abstract class for Scheduler's delegate.
*/
class SchedulerDelegate {
public:
/*
* Called right after Scheduler computed (and laid out) a new updated version
* of the tree and calculated a set of mutation instructions which are
* suffisient to construct a new one.
*/
virtual void schedulerDidComputeMutationInstructions(Tag rootTag, const TreeMutationInstructionList &instructions) = 0;
/*
* Called right after a new ShadowNode was created.
*/
virtual void schedulerDidRequestPreliminaryViewAllocation(ComponentName componentName) = 0;
};
} // namespace react
} // namespace facebook