Skip to content

Split scheduler commit and flush delegate methods #44188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions packages/react-native/React/Fabric/RCTScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN

- (void)schedulerDidFinishTransaction:(facebook::react::MountingCoordinator::Shared)mountingCoordinator;

- (void)schedulerShouldRenderTransactions:(facebook::react::MountingCoordinator::Shared)mountingCoordinator;

- (void)schedulerDidDispatchCommand:(const facebook::react::ShadowView &)shadowView
commandName:(const std::string &)commandName
args:(const folly::dynamic &)args;
Expand Down
6 changes: 6 additions & 0 deletions packages/react-native/React/Fabric/RCTScheduler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ void schedulerDidFinishTransaction(const MountingCoordinator::Shared &mountingCo
[scheduler.delegate schedulerDidFinishTransaction:mountingCoordinator];
}

void schedulerShouldRenderTransactions(const MountingCoordinator::Shared &mountingCoordinator) override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler.delegate schedulerShouldRenderTransactions:mountingCoordinator];
}

void schedulerDidRequestPreliminaryViewAllocation(SurfaceId surfaceId, const ShadowNode &shadowNode) override
{
// Does nothing.
Expand Down
11 changes: 10 additions & 1 deletion packages/react-native/React/Fabric/RCTSurfacePresenter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,16 @@ - (void)_applicationWillTerminate

- (void)schedulerDidFinishTransaction:(MountingCoordinator::Shared)mountingCoordinator
{
[_mountingManager scheduleTransaction:mountingCoordinator];
if (!ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop()) {
[_mountingManager scheduleTransaction:mountingCoordinator];
}
}

- (void)schedulerShouldRenderTransactions:(MountingCoordinator::Shared)mountingCoordinator
{
if (ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop()) {
[_mountingManager scheduleTransaction:mountingCoordinator];
}
}

- (void)schedulerDidDispatchCommand:(const ShadowView &)shadowView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,16 +462,38 @@ std::shared_ptr<FabricMountingManager> Binding::getMountingManager(

void Binding::schedulerDidFinishTransaction(
const MountingCoordinator::Shared& mountingCoordinator) {
auto mountingManager = getMountingManager("schedulerDidFinishTransaction");
if (!mountingManager) {
auto mountingTransaction = mountingCoordinator->pullTransaction();
if (!mountingTransaction.has_value()) {
return;
}

auto mountingTransaction = mountingCoordinator->pullTransaction();
if (!mountingTransaction.has_value()) {
auto pendingTransaction = std::find_if(
pendingTransactions_.begin(),
pendingTransactions_.end(),
[&](const auto& transaction) {
return transaction.getSurfaceId() ==
mountingTransaction->getSurfaceId();
});

if (pendingTransaction != pendingTransactions_.end()) {
pendingTransaction->mergeWith(std::move(*mountingTransaction));
} else {
pendingTransactions_.push_back(std::move(*mountingTransaction));
}
}

void Binding::schedulerShouldRenderTransactions(
const MountingCoordinator::Shared& /*mountingCoordinator*/) {
auto mountingManager =
getMountingManager("schedulerShouldRenderTransactions");
if (!mountingManager) {
return;
}
mountingManager->executeMount(*mountingTransaction);

for (auto& transaction : pendingTransactions_) {
mountingManager->executeMount(transaction);
}
pendingTransactions_.clear();
}

void Binding::schedulerDidRequestPreliminaryViewAllocation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class Binding : public jni::HybridClass<Binding, JBinding>,
void schedulerDidFinishTransaction(
const MountingCoordinator::Shared& mountingCoordinator) override;

void schedulerShouldRenderTransactions(
const MountingCoordinator::Shared& mountingCoordinator) override;

void schedulerDidRequestPreliminaryViewAllocation(
const SurfaceId surfaceId,
const ShadowNode& shadowNode) override;
Expand Down Expand Up @@ -146,6 +149,9 @@ class Binding : public jni::HybridClass<Binding, JBinding>,
std::shared_mutex
surfaceHandlerRegistryMutex_; // Protects `surfaceHandlerRegistry_`.

// Track pending transactions, one per surfaceId
std::vector<MountingTransaction> pendingTransactions_;

float pointScaleFactor_ = 1;

std::shared_ptr<const ReactNativeConfig> reactNativeConfig_{nullptr};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,17 @@ Number MountingTransaction::getNumber() const {
return number_;
}

void MountingTransaction::mergeWith(MountingTransaction&& transaction) {
react_native_assert(transaction.getSurfaceId() == surfaceId_);
number_ = transaction.getNumber();
mutations_.insert(
mutations_.end(),
std::make_move_iterator(transaction.mutations_.begin()),
std::make_move_iterator(transaction.mutations_.end()));

// TODO T186641819: Telemetry for merged transactions is not supported, use
// the latest instance
telemetry_ = std::move(transaction.telemetry_);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ class MountingTransaction final {
*/
Number getNumber() const;

/*
* Merges the given transaction in the current transaction, so they
* can be executed atomatically as a single transaction.
*/
void mergeWith(MountingTransaction&& transaction);

private:
SurfaceId surfaceId_;
Number number_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ void Scheduler::uiManagerDidFinishTransaction(
SystraceSection s("Scheduler::uiManagerDidFinishTransaction");

if (delegate_ != nullptr) {
delegate_->schedulerDidFinishTransaction(mountingCoordinator);

auto weakRuntimeScheduler =
contextContainer_->find<std::weak_ptr<RuntimeScheduler>>(
"RuntimeScheduler");
Expand All @@ -301,13 +303,14 @@ void Scheduler::uiManagerDidFinishTransaction(
runtimeScheduler->scheduleRenderingUpdate(
[delegate = delegate_,
mountingCoordinator = std::move(mountingCoordinator)]() {
delegate->schedulerDidFinishTransaction(mountingCoordinator);
delegate->schedulerShouldRenderTransactions(mountingCoordinator);
});
} else {
delegate_->schedulerDidFinishTransaction(mountingCoordinator);
delegate_->schedulerShouldRenderTransactions(mountingCoordinator);
}
}
}

void Scheduler::uiManagerDidCreateShadowNode(const ShadowNode& shadowNode) {
SystraceSection s("Scheduler::uiManagerDidCreateShadowNode");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ class SchedulerDelegate {
virtual void schedulerDidFinishTransaction(
const MountingCoordinator::Shared& mountingCoordinator) = 0;

/*
* Called when the runtime scheduler decides that one-or-more previously
* finished transactions should now be flushed to the screen (atomically).
*/
virtual void schedulerShouldRenderTransactions(
const MountingCoordinator::Shared& mountingCoordinator) = 0;

/*
* Called right after a new ShadowNode was created.
*/
Expand Down