Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,17 @@ NativeAnimatedNodesManager::ensureEventEmitterListener() noexcept {
}

void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {
// This method can be called from either the UI thread or JavaScript thread.
// It ensures `startOnRenderCallback_` is called exactly once using atomic
// operations. We use std::atomic_bool rather than std::mutex to avoid
// potential deadlocks that could occur if we called external code while
// holding a mutex.
auto isRenderCallbackStarted = isRenderCallbackStarted_.exchange(true);
if (isRenderCallbackStarted) {
// onRender callback is already started.
return;
}

if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
#ifdef RN_USE_ANIMATION_BACKEND
if (auto animationBackend = animationBackend_.lock()) {
Expand All @@ -531,16 +542,6 @@ void NativeAnimatedNodesManager::startRenderCallbackIfNeeded(bool isAsync) {

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

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

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

if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
if (isRenderCallbackStarted) {
if (auto animationBackend = animationBackend_.lock()) {
animationBackend->stop(isAsync);
}
}
return;
}

if (isRenderCallbackStarted) {
if (stopOnRenderCallback_) {
stopOnRenderCallback_(isAsync);
Expand Down
Loading