Fabric: Communicating a reason why a commit was unsuccessful via ShadowTree::CommitStatus

Summary:
We need it to stop repeating to commit new shadow tree in `ShadowTree::commit` when a transaction cancels the commit.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: JoshuaGross, sammy-SC

Differential Revision: D23603959

fbshipit-source-id: d279fb3bf4190e860740a6450595d6f2fc3117f7
This commit is contained in:
Valentin Shergin
2020-09-11 09:19:44 -07:00
committed by Facebook GitHub Bot
parent 1b943a99e0
commit c19b3ffae9
3 changed files with 27 additions and 17 deletions
@@ -21,6 +21,8 @@
namespace facebook {
namespace react {
using CommitStatus = ShadowTree::CommitStatus;
/*
* Generates (possibly) a new tree where all nodes with non-obsolete `State`
* objects. If all `State` objects in the tree are not obsolete for the moment
@@ -260,7 +262,7 @@ MountingCoordinator::Shared ShadowTree::getMountingCoordinator() const {
return mountingCoordinator_;
}
void ShadowTree::commit(
CommitStatus ShadowTree::commit(
ShadowTreeCommitTransaction transaction,
bool enableStateReconciliation) const {
SystraceSection s("ShadowTree::commit");
@@ -269,8 +271,10 @@ void ShadowTree::commit(
while (true) {
attempts++;
if (tryCommit(transaction, enableStateReconciliation)) {
return;
auto status = tryCommit(transaction, enableStateReconciliation);
if (status != CommitStatus::Failed) {
return status;
}
// After multiple attempts, we failed to commit the transaction.
@@ -279,7 +283,7 @@ void ShadowTree::commit(
}
}
bool ShadowTree::tryCommit(
CommitStatus ShadowTree::tryCommit(
ShadowTreeCommitTransaction transaction,
bool enableStateReconciliation) const {
SystraceSection s("ShadowTree::tryCommit");
@@ -298,7 +302,7 @@ bool ShadowTree::tryCommit(
RootShadowNode::Unshared newRootShadowNode = transaction(oldRootShadowNode);
if (!newRootShadowNode) {
return false;
return CommitStatus::Cancelled;
}
if (enableStateReconciliation) {
@@ -330,7 +334,7 @@ bool ShadowTree::tryCommit(
std::unique_lock<better::shared_mutex> lock(commitMutex_);
if (rootShadowNode_ != oldRootShadowNode) {
return false;
return CommitStatus::Failed;
}
rootShadowNode_ = newRootShadowNode;
@@ -356,7 +360,7 @@ bool ShadowTree::tryCommit(
notifyDelegatesOfUpdates();
return true;
return CommitStatus::Succeeded;
}
void ShadowTree::commitEmptyTree() const {
@@ -31,6 +31,12 @@ using ShadowTreeCommitTransaction = std::function<RootShadowNode::Unshared(
*/
class ShadowTree final {
public:
enum class CommitStatus {
Succeeded,
Failed,
Cancelled,
};
/*
* Creates a new shadow tree instance.
*/
@@ -53,17 +59,16 @@ class ShadowTree final {
/*
* Performs commit calling `transaction` function with a `oldRootShadowNode`
* and expecting a `newRootShadowNode` as a return value.
* The `transaction` function can abort commit returning `nullptr`.
* Returns `true` if the operation finished successfully.
* The `transaction` function can cancel commit returning `nullptr`.
*/
bool tryCommit(
CommitStatus tryCommit(
ShadowTreeCommitTransaction transaction,
bool enableStateReconciliation = false) const;
/*
* Calls `tryCommit` in a loop until it finishes successfully.
*/
void commit(
CommitStatus commit(
ShadowTreeCommitTransaction transaction,
bool enableStateReconciliation = false) const;
@@ -239,10 +239,10 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const {
shadowTreeRegistry_.visit(
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
bool updateSucceeded = shadowTree.tryCommit(
[&](RootShadowNode::Shared const &oldRootShadowNode) {
return std::static_pointer_cast<
RootShadowNode>(oldRootShadowNode->cloneTree(
auto status = shadowTree.tryCommit([&](RootShadowNode::Shared const
&oldRootShadowNode) {
return std::static_pointer_cast<RootShadowNode>(
oldRootShadowNode->cloneTree(
*family, [&](ShadowNode const &oldShadowNode) {
auto newData =
callback(oldShadowNode.getState()->getDataPointer());
@@ -256,8 +256,9 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const {
/* .state = */ newState,
});
}));
});
if (!updateSucceeded && stateUpdate.failureCallback) {
});
if (status != ShadowTree::CommitStatus::Succeeded &&
stateUpdate.failureCallback) {
stateUpdate.failureCallback();
}
});