Created
March 11, 2026 16:53
-
-
Save Shtille/b60a6b5c0609f7c49dcc4b3b487302af to your computer and use it in GitHub Desktop.
Children resolver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * The main idea of this class is to call some function when all children are ready. | |
| */ | |
| template<class Parent, class Child> | |
| class ChildResolver | |
| { | |
| typedef std::vector<Child*> ChildList; | |
| typedef std::unordered_set<Child*> ChildSet; | |
| typedef std::function<ChildList(Parent*)> ChildListFunction; | |
| typedef std::function<bool(Child*)> ChildReadyFunction; | |
| typedef std::function<void(Parent*)> ParentReadyFunction; | |
| public: | |
| ChildResolver(ChildListFunction child_list_func, ChildReadyFunction child_ready_func, ParentReadyFunction parent_ready_func) | |
| : m_childListFunction(child_list_func) | |
| , m_childReadyFunction(child_ready_func) | |
| , m_parentReadyFunction(parent_ready_func) | |
| {} | |
| // OnAppendRenderObject call this | |
| void Add(Parent* parent) | |
| { | |
| ChildList list = m_childListFunction(parent); | |
| auto pair = m_parentToChildrenMap.emplace(parent, std::move(list)); | |
| ChildList* children = &pair.first->second; | |
| ChildSet notReadySet; | |
| for (Child* child : *children) | |
| { | |
| if (!m_childReadyFunction(child)) | |
| notReadySet.insert(child); | |
| m_childToChildrenMap.emplace(child, std::make_pair<ChildList*, Parent*>(children, parent)); | |
| } | |
| m_notReadyChildren.emplace(children, std::move(notReadySet)); | |
| } | |
| // OnRemoveRenderObject call this | |
| void Remove(Parent* parent) | |
| { | |
| auto it = m_parentToChildrenMap.find(parent); | |
| ChildList* children = &it->second; | |
| for (Child* child : *children) | |
| { | |
| auto range = m_childToChildrenMap.equal_range(child); | |
| for (auto itr = range.first; itr != range.second;) | |
| if (itr->second.first == children) | |
| itr = m_childToChildrenMap.erase(itr); | |
| else | |
| ++itr; | |
| } | |
| m_notReadyChildren.erase(children); | |
| m_parentToChildrenMap.erase(it); | |
| } | |
| // call from outside | |
| void OnChildReady(Child* child) | |
| { | |
| // Find all children groups by child | |
| auto range = m_childToChildrenMap.equal_range(child); | |
| for (auto itr = range.first; itr != range.second; ++itr) | |
| { | |
| ChildList* children = itr->second.first; | |
| // Mark child ready (remove it from not ready set) | |
| auto it = m_notReadyChildren.find(children); | |
| if (it != m_notReadyChildren.end()) | |
| it->second.erase(child); | |
| // Check if all children are ready | |
| bool groupReady = it->second.empty(); | |
| if (groupReady) | |
| { | |
| Parent* parent = itr->second.second; | |
| m_parentReadyFunction(parent); | |
| } | |
| } | |
| } | |
| private: | |
| std::unordered_map<Parent*, ChildList> m_parentToChildrenMap; | |
| std::unordered_map<ChildList*, ChildSet> m_notReadyChildren; | |
| std::unordered_multimap<Child*, std::pair<ChildList*, Parent*>> m_childToChildrenMap; | |
| ChildListFunction m_childListFunction; | |
| ChildReadyFunction m_childReadyFunction; | |
| ParentReadyFunction m_parentReadyFunction; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment