Fabric: ShadowNodeFamily, maintaining a pointer to a parent family

Summary:
One of the core feature of ShadowNodeFamily is having a pointer to a parent family. This diff implements it.
I don't think there is a hard retain cycle there, but for more lean memory usage we use weak_ptr here.

Reviewed By: JoshuaGross

Differential Revision: D14416948

fbshipit-source-id: 05fd2c4833146f007228363b1d958776b4a2a9cf
This commit is contained in:
Valentin Shergin 2019-03-18 23:38:12 -07:00 коммит произвёл Facebook Github Bot
Родитель 28e89e5081
Коммит 978e59aa92
3 изменённых файлов: 42 добавлений и 0 удалений

Просмотреть файл

@ -46,6 +46,10 @@ ShadowNode::ShadowNode(
revision_(1) {
assert(props_);
assert(children_);
for (const auto &child : *children_) {
child->family_->setParent(family_);
}
}
ShadowNode::ShadowNode(
@ -71,6 +75,12 @@ ShadowNode::ShadowNode(
assert(props_);
assert(children_);
if (fragment.children) {
for (const auto &child : *children_) {
child->family_->setParent(family_);
}
}
}
UnsharedShadowNode ShadowNode::clone(const ShadowNodeFragment &fragment) const {
@ -139,6 +149,8 @@ void ShadowNode::appendChild(const SharedShadowNode &child) {
auto nonConstChildren =
std::const_pointer_cast<SharedShadowNodeList>(children_);
nonConstChildren->push_back(child);
child->family_->setParent(family_);
}
void ShadowNode::replaceChild(
@ -161,6 +173,8 @@ void ShadowNode::replaceChild(
std::replace(
nonConstChildren->begin(), nonConstChildren->end(), oldChild, newChild);
newChild->family_->setParent(family_);
}
void ShadowNode::setLocalData(const SharedLocalData &localData) {

Просмотреть файл

@ -20,5 +20,15 @@ ShadowNodeFamily::ShadowNodeFamily(
eventEmitter_(eventEmitter),
componentDescriptor_(componentDescriptor) {}
void ShadowNodeFamily::setParent(ShadowNodeFamily::Shared const &parent) const {
assert(parent_.lock() == nullptr || parent_.lock() == parent);
if (hasParent_) {
return;
}
parent_ = parent;
hasParent_ = true;
}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -32,6 +32,13 @@ class ShadowNodeFamily {
SharedEventEmitter const &eventEmitter,
ComponentDescriptor const &componentDescriptor);
/*
* Sets the parent.
* This is not techically thread-safe, but practically it mutates the object
* only once (and the model enforces that this first call is not concurent).
*/
void setParent(ShadowNodeFamily::Shared const &parent) const;
private:
friend ShadowNode;
@ -55,6 +62,17 @@ class ShadowNodeFamily {
* type.
*/
ComponentDescriptor const &componentDescriptor_;
/*
* Points to a family of all parent nodes of all nodes of the family.
*/
mutable ShadowNodeFamily::Weak parent_{};
/*
* Represents a case where `parent_` is `nullptr`.
* For optimization purposes only.
*/
mutable bool hasParent_{false};
};
} // namespace react