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:
parent
e90f5fa263
commit
4876928f9e
|
@ -38,6 +38,11 @@ Tag ShadowTree::getRootTag() const {
|
|||
return rootTag_;
|
||||
}
|
||||
|
||||
SharedRootShadowNode ShadowTree::getRootShadowNode() const {
|
||||
std::lock_guard<std::mutex> lock(commitMutex_);
|
||||
return rootShadowNode_;
|
||||
}
|
||||
|
||||
#pragma mark - Layout
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) {
|
||||
void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const {
|
||||
auto newRootShadowNode = cloneRootShadowNode(layoutConstraints, layoutContext);
|
||||
complete(newRootShadowNode);
|
||||
}
|
||||
|
@ -54,15 +59,15 @@ void ShadowTree::constraintLayout(const LayoutConstraints &layoutConstraints, co
|
|||
#pragma mark - Commiting
|
||||
|
||||
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);
|
||||
auto newRootShadowNode =
|
||||
std::make_shared<RootShadowNode>(*oldRootShadowNode, ShadowNodeFragment {.props = props});
|
||||
return newRootShadowNode;
|
||||
}
|
||||
|
||||
void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) {
|
||||
auto oldRootShadowNode = rootShadowNode_;
|
||||
void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) const {
|
||||
auto oldRootShadowNode = getRootShadowNode();
|
||||
auto newRootShadowNode =
|
||||
std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
|
@ -74,8 +79,8 @@ void ShadowTree::complete(const SharedShadowNodeUnsharedList &rootChildNodes) {
|
|||
complete(newRootShadowNode);
|
||||
}
|
||||
|
||||
void ShadowTree::complete(UnsharedRootShadowNode newRootShadowNode) {
|
||||
SharedRootShadowNode oldRootShadowNode = rootShadowNode_;
|
||||
void ShadowTree::complete(UnsharedRootShadowNode newRootShadowNode) const {
|
||||
SharedRootShadowNode oldRootShadowNode = getRootShadowNode();
|
||||
|
||||
newRootShadowNode->layout();
|
||||
|
||||
|
@ -99,7 +104,7 @@ bool ShadowTree::commit(
|
|||
const SharedRootShadowNode &oldRootShadowNode,
|
||||
const SharedRootShadowNode &newRootShadowNode,
|
||||
const ShadowViewMutationList &mutations
|
||||
) {
|
||||
) const {
|
||||
std::lock_guard<std::mutex> lock(commitMutex_);
|
||||
|
||||
if (oldRootShadowNode != rootShadowNode_) {
|
||||
|
@ -109,10 +114,11 @@ bool ShadowTree::commit(
|
|||
rootShadowNode_ = newRootShadowNode;
|
||||
|
||||
toggleEventEmitters(mutations);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShadowTree::emitLayoutEvents(const ShadowViewMutationList &mutations) {
|
||||
void ShadowTree::emitLayoutEvents(const ShadowViewMutationList &mutations) const {
|
||||
for (const auto &mutation : mutations) {
|
||||
// Only `Insert` and `Update` mutations can affect layout metrics.
|
||||
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());
|
||||
|
||||
for (const auto &mutation : mutations) {
|
||||
|
|
|
@ -49,17 +49,19 @@ public:
|
|||
/*
|
||||
* Applies given `layoutConstraints` and `layoutContext` and commit
|
||||
* the new shadow tree.
|
||||
* Returns `true` if the operation is finished successfully.
|
||||
* 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
|
||||
|
||||
/*
|
||||
* Create a new shadow tree with given `rootChildNodes` and commit.
|
||||
* 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
|
||||
|
||||
|
@ -74,17 +76,22 @@ public:
|
|||
private:
|
||||
|
||||
UnsharedRootShadowNode cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
|
||||
void complete(UnsharedRootShadowNode newRootShadowNode);
|
||||
void complete(UnsharedRootShadowNode newRootShadowNode) const;
|
||||
bool commit(
|
||||
const SharedRootShadowNode &oldRootShadowNode,
|
||||
const SharedRootShadowNode &newRootShadowNode,
|
||||
const ShadowViewMutationList &mutations
|
||||
);
|
||||
void toggleEventEmitters(const ShadowViewMutationList &mutations);
|
||||
void emitLayoutEvents(const ShadowViewMutationList &mutations);
|
||||
) const;
|
||||
void toggleEventEmitters(const ShadowViewMutationList &mutations) const;
|
||||
void emitLayoutEvents(const ShadowViewMutationList &mutations) const;
|
||||
|
||||
/*
|
||||
* Return `rootShadowNodeMutex_` protected by `commitMutex_`.
|
||||
*/
|
||||
SharedRootShadowNode getRootShadowNode() const;
|
||||
|
||||
const Tag rootTag_;
|
||||
SharedRootShadowNode rootShadowNode_;
|
||||
mutable SharedRootShadowNode rootShadowNode_; // Protected by `commitMutex_`.
|
||||
ShadowTreeDelegate const *delegate_;
|
||||
mutable std::mutex commitMutex_;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue