diff --git a/React/Fabric/RCTScheduler.h b/React/Fabric/RCTScheduler.h index b69e9207e..d747032a1 100644 --- a/React/Fabric/RCTScheduler.h +++ b/React/Fabric/RCTScheduler.h @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN layoutContext:(facebook::react::LayoutContext)layoutContext surfaceId:(facebook::react::SurfaceId)surfaceId; -- (BOOL)constraintSurfaceLayoutWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints +- (void)constraintSurfaceLayoutWithLayoutConstraints:(facebook::react::LayoutConstraints)layoutConstraints layoutContext:(facebook::react::LayoutContext)layoutContext surfaceId:(facebook::react::SurfaceId)surfaceId; diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 3755a0966..7a1822dd9 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -80,11 +80,11 @@ private: return RCTCGSizeFromSize(_scheduler->measureSurface(surfaceId, layoutConstraints, layoutContext)); } -- (BOOL)constraintSurfaceLayoutWithLayoutConstraints:(LayoutConstraints)layoutConstraints +- (void)constraintSurfaceLayoutWithLayoutConstraints:(LayoutConstraints)layoutConstraints layoutContext:(LayoutContext)layoutContext surfaceId:(SurfaceId)surfaceId { - return _scheduler->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext); + _scheduler->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext); } @end diff --git a/React/Fabric/RCTSurfacePresenter.h b/React/Fabric/RCTSurfacePresenter.h index 762066011..9e1931835 100644 --- a/React/Fabric/RCTSurfacePresenter.h +++ b/React/Fabric/RCTSurfacePresenter.h @@ -57,9 +57,8 @@ NS_ASSUME_NONNULL_BEGIN /** * Sets `minimumSize` and `maximumSize` layout constraints for the Surface. - * Returns `YES` if the operation finished successfully. */ -- (BOOL)setMinimumSize:(CGSize)minimumSize +- (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize surface:(RCTFabricSurface *)surface; diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 85c2ae0e6..bf3344025 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -119,7 +119,7 @@ using namespace facebook::react; surfaceId:surface.rootTag]; } -- (BOOL)setMinimumSize:(CGSize)minimumSize +- (void)setMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize surface:(RCTFabricSurface *)surface { @@ -129,9 +129,9 @@ using namespace facebook::react; layoutConstraints.minimumSize = RCTSizeFromCGSize(minimumSize); layoutConstraints.maximumSize = RCTSizeFromCGSize(maximumSize); - return [self._scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints - layoutContext:layoutContext - surfaceId:surface.rootTag]; + [self._scheduler constraintSurfaceLayoutWithLayoutConstraints:layoutConstraints + layoutContext:layoutContext + surfaceId:surface.rootTag]; } #pragma mark - Private diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp index 84b8ef205..a09a40a66 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.cpp +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -94,7 +94,7 @@ Size Scheduler::measureSurface( return shadowTree->measure(layoutConstraints, layoutContext); } -bool Scheduler::constraintSurfaceLayout( +void Scheduler::constraintSurfaceLayout( SurfaceId surfaceId, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext @@ -102,7 +102,9 @@ bool Scheduler::constraintSurfaceLayout( std::lock_guard lock(mutex_); const auto &shadowTree = shadowTreeRegistry_.at(surfaceId); assert(shadowTree); - return shadowTree->constraintLayout(layoutConstraints, layoutContext); + shadowTree->synchronize([&]() { + shadowTree->constraintLayout(layoutConstraints, layoutContext); + }); } #pragma mark - Delegate diff --git a/ReactCommon/fabric/uimanager/Scheduler.h b/ReactCommon/fabric/uimanager/Scheduler.h index a7fcf5bd7..bed761c1f 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.h +++ b/ReactCommon/fabric/uimanager/Scheduler.h @@ -53,10 +53,9 @@ public: * The user interface will be relaid out as a result. The operation will be * performed synchronously (including mounting) if the method is called * on the main thread. - * Returns `true` if the operation finished successfully. * Can be called from any thread. */ - bool constraintSurfaceLayout( + void constraintSurfaceLayout( SurfaceId surfaceId, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext diff --git a/ReactCommon/fabric/uimanager/ShadowTree.cpp b/ReactCommon/fabric/uimanager/ShadowTree.cpp index 9bd4ce0a2..872f90806 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.cpp +++ b/ReactCommon/fabric/uimanager/ShadowTree.cpp @@ -39,10 +39,15 @@ Tag ShadowTree::getRootTag() const { } SharedRootShadowNode ShadowTree::getRootShadowNode() const { - std::lock_guard lock(commitMutex_); + std::lock_guard lock(commitMutex_); return rootShadowNode_; } +void ShadowTree::synchronize(std::function function) const { + std::lock_guard lock(commitMutex_); + function(); +} + #pragma mark - Layout Size ShadowTree::measure(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const { @@ -109,7 +114,7 @@ bool ShadowTree::commit( const SharedRootShadowNode &newRootShadowNode, const ShadowViewMutationList &mutations ) const { - std::lock_guard lock(commitMutex_); + std::lock_guard lock(commitMutex_); if (oldRootShadowNode != rootShadowNode_) { return false; diff --git a/ReactCommon/fabric/uimanager/ShadowTree.h b/ReactCommon/fabric/uimanager/ShadowTree.h index ff6cef9db..a0f6bee18 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.h +++ b/ReactCommon/fabric/uimanager/ShadowTree.h @@ -38,6 +38,16 @@ public: */ Tag getRootTag() const; + /* + * Synchronously runs `function` when `commitMutex_` is acquired. + * It is useful in cases when transactional consistency and/or successful + * commit are required. E.g. you might want to run `measure` and + * `constraintLayout` as part of a single congious transaction. + * Use this only if it is necessary. All public methods of the class are + * already thread-safe. + */ + void synchronize(std::function function) const; + #pragma mark - Layout /* @@ -93,7 +103,7 @@ private: const Tag rootTag_; mutable SharedRootShadowNode rootShadowNode_; // Protected by `commitMutex_`. ShadowTreeDelegate const *delegate_; - mutable std::mutex commitMutex_; + mutable std::recursive_mutex commitMutex_; }; } // namespace react