mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-29 04:35:36 +08:00
Fabric: Improved thread-safety in ShadowTree
Summary: With new `ShadowTree::getRootShadowNode()` method all access to rootShadowNode_ is protected by commit mutex. Reviewed By: mdvacca Differential Revision: D10159456 fbshipit-source-id: 0bc8676ca2564a8ef95d60e912356e99d9f172c1
This commit is contained in:
committed by
Facebook Github Bot
parent
e90f5fa263
commit
4876928f9e
@@ -38,6 +38,11 @@ Tag ShadowTree::getRootTag() const {
|
|||||||
return rootTag_;
|
return rootTag_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedRootShadowNode ShadowTree::getRootShadowNode() const {
|
||||||
|
std::lock_guard<std::mutex> lock(commitMutex_);
|
||||||
|
return rootShadowNode_;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Layout
|
#pragma mark - Layout
|
||||||
|
|
||||||
Size ShadowTree::measure(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
Size ShadowTree::measure(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
||||||
@@ -46,7 +51,7 @@ Size ShadowTree::measure(const LayoutConstraints &layoutConstraints, const Layou
|
|||||||
return newRootShadowNode->getLayoutMetrics().frame.size;
|
return newRootShadowNode->getLayoutMetrics().frame.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) {
|
void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
||||||
auto newRootShadowNode = cloneRootShadowNode(layoutConstraints, layoutContext);
|
auto newRootShadowNode = cloneRootShadowNode(layoutConstraints, layoutContext);
|
||||||
complete(newRootShadowNode);
|
complete(newRootShadowNode);
|
||||||
}
|
}
|
||||||
@@ -54,15 +59,15 @@ void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, co
|
|||||||
#pragma mark - Commiting
|
#pragma mark - Commiting
|
||||||
|
|
||||||
UnsharedRootShadowNode ShadowTree::cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
UnsharedRootShadowNode ShadowTree::cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
||||||
auto oldRootShadowNode = rootShadowNode_;
|
auto oldRootShadowNode = getRootShadowNode();
|
||||||
const auto &props = std::make_shared<const RootProps>(*oldRootShadowNode->getProps(), layoutConstraints, layoutContext);
|
const auto &props = std::make_shared<const RootProps>(*oldRootShadowNode->getProps(), layoutConstraints, layoutContext);
|
||||||
auto newRootShadowNode =
|
auto newRootShadowNode =
|
||||||
std::make_shared<RootShadowNode>(*oldRootShadowNode, ShadowNodeFragment {.props = props});
|
std::make_shared<RootShadowNode>(*oldRootShadowNode, ShadowNodeFragment {.props = props});
|
||||||
return newRootShadowNode;
|
return newRootShadowNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) {
|
void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) const {
|
||||||
auto oldRootShadowNode = rootShadowNode_;
|
auto oldRootShadowNode = getRootShadowNode();
|
||||||
auto newRootShadowNode =
|
auto newRootShadowNode =
|
||||||
std::make_shared<RootShadowNode>(
|
std::make_shared<RootShadowNode>(
|
||||||
*oldRootShadowNode,
|
*oldRootShadowNode,
|
||||||
@@ -74,8 +79,8 @@ void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) {
|
|||||||
complete(newRootShadowNode);
|
complete(newRootShadowNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowTree::complete(UnsharedRootShadowNode newRootShadowNode) {
|
void ShadowTree::complete(UnsharedRootShadowNode newRootShadowNode) const {
|
||||||
SharedRootShadowNode oldRootShadowNode = rootShadowNode_;
|
SharedRootShadowNode oldRootShadowNode = getRootShadowNode();
|
||||||
|
|
||||||
newRootShadowNode->layout();
|
newRootShadowNode->layout();
|
||||||
|
|
||||||
@@ -99,7 +104,7 @@ bool ShadowTree::commit(
|
|||||||
const SharedRootShadowNode &oldRootShadowNode,
|
const SharedRootShadowNode &oldRootShadowNode,
|
||||||
const SharedRootShadowNode &newRootShadowNode,
|
const SharedRootShadowNode &newRootShadowNode,
|
||||||
const ShadowViewMutationList &mutations
|
const ShadowViewMutationList &mutations
|
||||||
) {
|
) const {
|
||||||
std::lock_guard<std::mutex> lock(commitMutex_);
|
std::lock_guard<std::mutex> lock(commitMutex_);
|
||||||
|
|
||||||
if (oldRootShadowNode != rootShadowNode_) {
|
if (oldRootShadowNode != rootShadowNode_) {
|
||||||
@@ -109,10 +114,11 @@ bool ShadowTree::commit(
|
|||||||
rootShadowNode_ = newRootShadowNode;
|
rootShadowNode_ = newRootShadowNode;
|
||||||
|
|
||||||
toggleEventEmitters(mutations);
|
toggleEventEmitters(mutations);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowTree::emitLayoutEvents(const ShadowViewMutationList &mutations) {
|
void ShadowTree::emitLayoutEvents(const ShadowViewMutationList &mutations) const {
|
||||||
for (const auto &mutation : mutations) {
|
for (const auto &mutation : mutations) {
|
||||||
// Only `Insert` and `Update` mutations can affect layout metrics.
|
// Only `Insert` and `Update` mutations can affect layout metrics.
|
||||||
if (
|
if (
|
||||||
@@ -147,7 +153,7 @@ void ShadowTree::emitLayoutEvents(const ShadowViewMutationList &mutations) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowTree::toggleEventEmitters(const ShadowViewMutationList &mutations) {
|
void ShadowTree::toggleEventEmitters(const ShadowViewMutationList &mutations) const {
|
||||||
std::lock_guard<std::recursive_mutex> lock(EventEmitter::DispatchMutex());
|
std::lock_guard<std::recursive_mutex> lock(EventEmitter::DispatchMutex());
|
||||||
|
|
||||||
for (const auto &mutation : mutations) {
|
for (const auto &mutation : mutations) {
|
||||||
|
|||||||
@@ -49,17 +49,19 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Applies given `layoutConstraints` and `layoutContext` and commit
|
* Applies given `layoutConstraints` and `layoutContext` and commit
|
||||||
* the new shadow tree.
|
* the new shadow tree.
|
||||||
|
* Returns `true` if the operation is finished successfully.
|
||||||
* Can be called from any thread.
|
* Can be called from any thread.
|
||||||
*/
|
*/
|
||||||
void constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext);
|
void constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
|
||||||
|
|
||||||
#pragma mark - Application
|
#pragma mark - Application
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new shadow tree with given `rootChildNodes` and commit.
|
* Create a new shadow tree with given `rootChildNodes` and commit.
|
||||||
* Can be called from any thread.
|
* Can be called from any thread.
|
||||||
|
* Returns `true` if the operation is finished successfully.
|
||||||
*/
|
*/
|
||||||
void complete(const SharedShadowNodeUnsharedList &rootChildNodes);
|
void complete(const SharedShadowNodeUnsharedList &rootChildNodes) const;
|
||||||
|
|
||||||
#pragma mark - Delegate
|
#pragma mark - Delegate
|
||||||
|
|
||||||
@@ -74,17 +76,22 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
UnsharedRootShadowNode cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
|
UnsharedRootShadowNode cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
|
||||||
void complete(UnsharedRootShadowNode newRootShadowNode);
|
void complete(UnsharedRootShadowNode newRootShadowNode) const;
|
||||||
bool commit(
|
bool commit(
|
||||||
const SharedRootShadowNode &oldRootShadowNode,
|
const SharedRootShadowNode &oldRootShadowNode,
|
||||||
const SharedRootShadowNode &newRootShadowNode,
|
const SharedRootShadowNode &newRootShadowNode,
|
||||||
const ShadowViewMutationList &mutations
|
const ShadowViewMutationList &mutations
|
||||||
);
|
) const;
|
||||||
void toggleEventEmitters(const ShadowViewMutationList &mutations);
|
void toggleEventEmitters(const ShadowViewMutationList &mutations) const;
|
||||||
void emitLayoutEvents(const ShadowViewMutationList &mutations);
|
void emitLayoutEvents(const ShadowViewMutationList &mutations) const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return `rootShadowNodeMutex_` protected by `commitMutex_`.
|
||||||
|
*/
|
||||||
|
SharedRootShadowNode getRootShadowNode() const;
|
||||||
|
|
||||||
const Tag rootTag_;
|
const Tag rootTag_;
|
||||||
SharedRootShadowNode rootShadowNode_;
|
mutable SharedRootShadowNode rootShadowNode_; // Protected by `commitMutex_`.
|
||||||
ShadowTreeDelegate const *delegate_;
|
ShadowTreeDelegate const *delegate_;
|
||||||
mutable std::mutex commitMutex_;
|
mutable std::mutex commitMutex_;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user