Fabric: MountingCoordinator::revoke()

Summary:
MountingCoordinator is a borderline between Core and Mounting. Some of Core design constraints are impossible/impractical to enforce on Mounting layer, so we have to handle all of those cases in `MountingCoordinator`.

One of the constrains is that all ShadowNodes implicitly depend on associated ComponentDescriptor instances without retaining them (retaining is expensive and creates a retain cycle).
The problem is that the Mounting layer can call `MountingCoordinator::pull()` at any moment (even after the whole Core is already destroyed). To prevent this, the owner of a `MountingCoordinator` on the Core side calls `revoke()` right before being deallocated (right before the moment the owner cannot guarantee the constraint).

Reviewed By: JoshuaGross

Differential Revision: D17272295

fbshipit-source-id: ba8b02eab8f84cce68aa65c1ad36950cd2498049
This commit is contained in:
Valentin Shergin
2019-09-09 20:26:25 -07:00
committed by Facebook Github Bot
parent 27fca36a9a
commit 28a5f122a8
4 changed files with 16 additions and 1 deletions
@@ -83,7 +83,7 @@ class LayoutableShadowNode : public virtual Sealable {
/*
* Clean or Dirty layout state:
* Indicates whether all nodes (and possibly their subtrees) along the path
* to the root node should be re-layouted.
* to the root node should be re-laid out.
*/
virtual void cleanLayout() = 0;
virtual void dirtyLayout() = 0;
@@ -44,6 +44,11 @@ void MountingCoordinator::push(ShadowTreeRevision &&revision) const {
}
}
void MountingCoordinator::revoke() const {
std::lock_guard<std::mutex> lock(mutex_);
lastRevision_.reset();
}
better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
const {
std::lock_guard<std::mutex> lock(mutex_);
@@ -60,6 +60,15 @@ class MountingCoordinator final {
*/
void push(ShadowTreeRevision &&revision) const;
/*
* Revokes the last pushed `ShadowTreeRevision`.
* Generating a `MountingTransaction` requires some resources which the
* `MountingCoordinator` does not own (e.g. `ComponentDescriptor`s). Revoking
* committed revisions allows the owner (a Shadow Tree) to make sure that
* those resources will not be accessed (e.g. by the Mouting Layer).
*/
void revoke() const;
private:
SurfaceId const surfaceId_;
@@ -116,6 +116,7 @@ ShadowTree::~ShadowTree() {
/* .children = */ ShadowNode::emptySharedShadowNodeSharedList(),
});
});
mountingCoordinator_->revoke();
}
Tag ShadowTree::getSurfaceId() const {