Skip to content

Commit

Permalink
Implement thread-safety for LazyShadowTreeRevisionConsistencyManager
Browse files Browse the repository at this point in the history
Summary:
Some methods in `LazyShadowTreeRevisionConsistencyManager` can be called in parallel when using synchronous state updates (which is also behind a flag). This implements thread-safety to cover that case so we don't have issues when testing that variant in production.

Changelog: [internal]

Differential Revision: D57506540
  • Loading branch information
rubennorte authored and facebook-github-bot committed May 20, 2024
1 parent fbf9c43 commit e092d6a
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ LazyShadowTreeRevisionConsistencyManager::
void LazyShadowTreeRevisionConsistencyManager::updateCurrentRevision(
SurfaceId surfaceId,
RootShadowNode::Shared rootShadowNode) {
std::unique_lock lock(capturedRootShadowNodesForConsistencyMutex_);
capturedRootShadowNodesForConsistency_[surfaceId] = std::move(rootShadowNode);
}

Expand All @@ -26,6 +27,8 @@ void LazyShadowTreeRevisionConsistencyManager::updateCurrentRevision(
RootShadowNode::Shared
LazyShadowTreeRevisionConsistencyManager::getCurrentRevision(
SurfaceId surfaceId) {
std::unique_lock lock(capturedRootShadowNodesForConsistencyMutex_);

auto it = capturedRootShadowNodesForConsistency_.find(surfaceId);
if (it != capturedRootShadowNodesForConsistency_.end()) {
return it->second;
Expand Down Expand Up @@ -65,6 +68,8 @@ void LazyShadowTreeRevisionConsistencyManager::unlockRevisions() {
}

isLocked_ = false;

std::unique_lock lock(capturedRootShadowNodesForConsistencyMutex_);
capturedRootShadowNodesForConsistency_.clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <react/renderer/mounting/ShadowTreeRegistry.h>
#include <react/renderer/uimanager/consistency/ShadowTreeRevisionProvider.h>
#include <memory>
#include <shared_mutex>

namespace facebook::react {

Expand Down Expand Up @@ -42,6 +43,7 @@ class LazyShadowTreeRevisionConsistencyManager
void unlockRevisions() override;

private:
std::shared_mutex capturedRootShadowNodesForConsistencyMutex_;
std::unordered_map<SurfaceId, RootShadowNode::Shared>
capturedRootShadowNodesForConsistency_;
ShadowTreeRegistry& shadowTreeRegistry_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,33 @@ TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testLockAfterUnlock) {
consistencyManager_.unlockRevisions();
}

TEST_F(LazyShadowTreeRevisionConsistencyManagerTest, testUpdateToUnmounted) {
shadowTreeRegistry_.add(createShadowTree(0));

auto element = Element<RootShadowNode>();
auto builder = simpleComponentBuilder();
auto newRootShadowNode = builder.build(element);

shadowTreeRegistry_.visit(
0, [newRootShadowNode](const ShadowTree& shadowTree) {
shadowTree.commit(
[&](const RootShadowNode& /*oldRootShadowNode*/) {
return newRootShadowNode;
},
{});
});

consistencyManager_.lockRevisions();

EXPECT_EQ(
consistencyManager_.getCurrentRevision(0).get(), newRootShadowNode.get());

consistencyManager_.updateCurrentRevision(0, nullptr);

// Updated
EXPECT_EQ(consistencyManager_.getCurrentRevision(0).get(), nullptr);

consistencyManager_.unlockRevisions();
}

} // namespace facebook::react

0 comments on commit e092d6a

Please sign in to comment.