Skip to content

Commit 8b95fce

Browse files
Bartlomiej Bloniarzmeta-codesync[bot]
authored andcommitted
Start AnimationBackend callbacks once per frame in Animated (#54426)
Summary: Pull Request resolved: #54426 Withouth the backend, Animated triggers the start function once per frame (by updating an atomic bool). We now do the same with animation backend. # Changelog [General] [Changed] - Move the animation backend callback scheduling, behind the `isRenderCallbackStarted` check. Reviewed By: zeyap Differential Revision: D85234259 fbshipit-source-id: 3aaf5f66de1dce4c5563f85bea22f0aa862801bb
1 parent 0eda52a commit 8b95fce

1 file changed

Lines changed: 20 additions & 16 deletions

File tree

packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,17 @@ NativeAnimatedNodesManager::ensureEventEmitterListener() noexcept {
519519
}
520520

521521
void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
522+
// This method can be called from either the UI thread or JavaScript thread.
523+
// It ensures `startOnRenderCallback_` is called exactly once using atomic
524+
// operations. We use std::atomic_bool rather than std::mutex to avoid
525+
// potential deadlocks that could occur if we called external code while
526+
// holding a mutex.
527+
auto isRenderCallbackStarted = isRenderCallbackStarted_.exchange(true);
528+
if (isRenderCallbackStarted) {
529+
// onRender callback is already started.
530+
return;
531+
}
532+
522533
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
523534
#ifdef RN_USE_ANIMATION_BACKEND
524535
if (auto animationBackend = animationBackend_.lock()) {
@@ -531,16 +542,6 @@ void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
531542

532543
return;
533544
}
534-
// This method can be called from either the UI thread or JavaScript thread.
535-
// It ensures `startOnRenderCallback_` is called exactly once using atomic
536-
// operations. We use std::atomic_bool rather than std::mutex to avoid
537-
// potential deadlocks that could occur if we called external code while
538-
// holding a mutex.
539-
auto isRenderCallbackStarted = isRenderCallbackStarted_.exchange(true);
540-
if (isRenderCallbackStarted) {
541-
// onRender callback is already started.
542-
return;
543-
}
544545

545546
if (startOnRenderCallback_) {
546547
startOnRenderCallback_([this]() { onRender(); }, isAsync);
@@ -549,18 +550,21 @@ void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
549550

550551
void NativeAnimatedNodesManager::stopRenderCallbackIfNeeded(
551552
bool isAsync) noexcept {
552-
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
553-
if (auto animationBackend = animationBackend_.lock()) {
554-
animationBackend->stop(isAsync);
555-
}
556-
return;
557-
}
558553
// When multiple threads reach this point, only one thread should call
559554
// stopOnRenderCallback_. This synchronization is primarily needed during
560555
// destruction of NativeAnimatedNodesManager. In normal operation,
561556
// stopRenderCallbackIfNeeded is always called from the UI thread.
562557
auto isRenderCallbackStarted = isRenderCallbackStarted_.exchange(false);
563558

559+
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
560+
if (isRenderCallbackStarted) {
561+
if (auto animationBackend = animationBackend_.lock()) {
562+
animationBackend->stop(isAsync);
563+
}
564+
}
565+
return;
566+
}
567+
564568
if (isRenderCallbackStarted) {
565569
if (stopOnRenderCallback_) {
566570
stopOnRenderCallback_(isAsync);

0 commit comments

Comments
 (0)