From ba45895a3f7b54cf2b0bf93daaf6b362726e14df Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Tue, 10 Apr 2018 12:46:20 -0700 Subject: [PATCH] Fabric: Introducing Scheduler Summary: Scheduler coordinates Shadow Tree updates and event flows (not yet). Reviewed By: mdvacca Differential Revision: D7503387 fbshipit-source-id: 4cb8bc574c25a0fd2ace6319c26c644a1e4757a9 --- ReactCommon/fabric/uimanager/Scheduler.cpp | 108 ++++++++++++++++++ ReactCommon/fabric/uimanager/Scheduler.h | 74 ++++++++++++ .../fabric/uimanager/SchedulerDelegate.h | 33 ++++++ 3 files changed, 215 insertions(+) create mode 100644 ReactCommon/fabric/uimanager/Scheduler.cpp create mode 100644 ReactCommon/fabric/uimanager/Scheduler.h create mode 100644 ReactCommon/fabric/uimanager/SchedulerDelegate.h diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp new file mode 100644 index 000000000..b2571ebf6 --- /dev/null +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -0,0 +1,108 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "Scheduler.h" + +#include +#include +#include +#include +#include +#include + +#include "Differentiator.h" + +namespace facebook { +namespace react { + +Scheduler::Scheduler() { + auto componentDescriptorRegistry = std::make_shared(); + SharedComponentDescriptor viewComponentDescriptor = std::make_shared(); + componentDescriptorRegistry->registerComponentDescriptor(viewComponentDescriptor); + + uiManager_ = std::make_shared(componentDescriptorRegistry); + uiManager_->setDelegate(this); +} + +Scheduler::~Scheduler() { + uiManager_->setDelegate(nullptr); +} + +void Scheduler::registerRootTag(Tag rootTag) { + auto rootShadowNode = std::make_shared(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(oldRootShadowNode, nullptr, SharedShadowNodeSharedList(rootChildNodes)); + + auto nonConstOldRootShadowNode = std::const_pointer_cast(oldRootShadowNode); + auto nonConstNewRootShadowNode = std::const_pointer_cast(newRootShadowNode); + + LayoutContext layoutContext = LayoutContext(); + layoutContext.affectedShadowNodes = std::make_shared>(); + + 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 Scheduler::getUIManager_DO_NOT_USE() { + return uiManager_; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/uimanager/Scheduler.h b/ReactCommon/fabric/uimanager/Scheduler.h new file mode 100644 index 000000000..4f4ff203b --- /dev/null +++ b/ReactCommon/fabric/uimanager/Scheduler.h @@ -0,0 +1,74 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include + +#include +#include +#include +#include +#include + +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 getUIManager_DO_NOT_USE(); + +private: + SchedulerDelegate *delegate_; + std::shared_ptr uiManager_; + + /* + * All commited `RootShadowNode` instances to differentiate against. + */ + std::unordered_map rootNodeRegistry_; +}; + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/uimanager/SchedulerDelegate.h b/ReactCommon/fabric/uimanager/SchedulerDelegate.h new file mode 100644 index 000000000..2fe3da02a --- /dev/null +++ b/ReactCommon/fabric/uimanager/SchedulerDelegate.h @@ -0,0 +1,33 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include + +#include +#include +#include + +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