The Sparta Modeling Framework
Loading...
Searching...
No Matches
TreeNode.hpp
Go to the documentation of this file.
1// <TreeNode> -*- C++ -*-
2
3
9#pragma once
10
11#include <cstddef>
12#include <cstdint>
13#include <iostream>
14#include <fstream>
15#include <string>
16#include <ostream>
17#include <vector>
18#include <sstream>
19#include <set>
20#include <map>
21#include <unordered_map>
22#include <regex>
23#include <functional>
24#include <memory>
25#include <type_traits>
26#include <typeinfo>
27#include <utility>
28
32#include "sparta/utils/Utils.hpp"
36#include "sparta/utils/StringManager.hpp"
38
39namespace sparta {
40class PostRunValidationInfo;
41} // namespace sparta
42
43#ifndef TREENODE_LIFETIME_TRACE
52//#define TREENODE_LIFETIME_TRACE 1
53#endif // #ifndef TREENODE_LIFETIME_TRACE
54
55
57#define ALPHANUM_CHARS \
58 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_"
59
61#define DIGIT_CHARS "0123456789"
62
68#define RESERVED_WORDS {"and", "del", "from", "not", \
69 "while", "as", "elif", "global", \
70 "or", "with", "assert", "else", \
71 "if", "pass", "yield", "break", \
72 "except", "import", "print", "class", \
73 "exec", "in", "raise", "continue", \
74 "finally", "is", "return", "def", \
75 "for", "lambda", "try", "__init__", \
76 "__del__", "__cinit__", "__dealloc__", \
77 /* End of Python reserved names */ \
78 "name", "author", "report", "content", \
79 "include", \
80 /* End of SPARTA Report definition reserved nodes */ \
81 "extension" \
82 /* End of SPARTA extensions reserved words */ \
83 }
84
148#define REGISTER_FOR_NOTIFICATION(func, datat, name) \
149 registerForNotification<datat, \
150 typename std::remove_reference<decltype(*this)>::type, \
151 &std::remove_reference<decltype(*this)>::type::func>(this, name);
152
158#define DEREGISTER_FOR_NOTIFICATION(func, datat, name) \
159 deregisterForNotification<datat, \
160 typename std::remove_reference<decltype(*this)>::type, \
161 &std::remove_reference<decltype(*this)>::type::func>(this, name);
162
163#define NOTIFY(func, datat, name) \
164
165
166namespace sparta
167{
168 namespace app {
169 class Simulation;
170 }
171
172 class Clock;
173 class VirtualGlobalTreeNode;
174 class ClockManager;
175 class TreeNodePrivateAttorney;
176 class ParameterSet;
177 class Scheduler;
178 class ExtensionDescriptor;
179
180 typedef std::vector<std::unique_ptr<ExtensionDescriptor>> ExtensionDescriptorVec;
181
205 {
206 public:
213
217 friend class ClockManager;
218
224
230
234
238 typedef uint64_t node_uid_type;
239
243 typedef std::vector<TreeNode*> ChildrenVector;
244
248 typedef std::vector<std::string> AliasVector;
249
256 typedef std::multimap<std::string, TreeNode*> ChildNameMapping;
257
261 typedef uint32_t group_idx_type;
262
266 typedef std::weak_ptr<TreeNode> WeakPtr;
267
271 typedef std::weak_ptr<const TreeNode> ConstWeakPtr;
272
276 typedef std::shared_ptr<TreeNode> SharedPtr;
277
281 typedef std::map<const std::string*, std::vector<TreeNode*>> TagsMap;
282
290 struct ANY_TYPE {};
291
294
298
304
310
314 static constexpr char GROUP_NAME_NONE[] = "";
315
319 static constexpr char NODE_NAME_NONE[] = "";
320
324 static const std::string DEBUG_DUMP_SECTION_DIVIDER;
325
329 static constexpr char NODE_NAME_VIRTUAL_GLOBAL[] = "_SPARTA_virtual_global_";
330
337 static constexpr char LOCATION_NODE_SEPARATOR_ATTACHED = '.';
338
346 static constexpr char LOCATION_NODE_SEPARATOR_EXPECTING = ',';
347
355 static constexpr char LOCATION_NODE_SEPARATOR_UNATTACHED = '~';
356
362 static const uint32_t RENDER_SUBTREE_INDENT = 2;
363
370 static constexpr char GROUP_NAME_BUILTIN[] = "_SPARTA_builtin_group_";
371
392 static const uint64_t CHILD_FIND_THRESHOLD = 100000;
393
400 static const uint64_t CHILD_GET_THRESHOLD = 100000;
401
406 static const uint32_t TEARDOWN_ERROR_LIMIT = 5;
407
412 static const std::vector<std::pair<const char*, std::function<void (std::string&)>>> TREE_NODE_PATTERN_SUBS;
413
416
420
433 throw SpartaException("Device tree with root \"")
434 << getRoot()->getLocation() << "\" not currently in the TREE_BUILDING phase or "
435 << "TREE_CONFIGURING phase, so it cannot enter TREE_LOCKDOWN";
436 }
437 lockdownParametersUtil_();
438 }
439
440 static const std::map<const TreeNode*, WeakPtr>& getParentlessNodes();
441
446 static const std::map<const TreeNode*, WeakPtr>& getAllNodes();
447
452 static std::string formatAllNodes();
453
458 static bool isNodeConstructed(const TreeNode*);
459
462
466
468 TreeNode() = delete;
469
473 TreeNode(const TreeNode&) = delete;
474
485
487 TreeNode& operator=(const TreeNode&) = delete;
488
573 const std::string& name,
574 const std::string& group,
575 group_idx_type group_idx,
576 const std::string& desc,
577 bool is_indexable);
578
585 const std::string& name,
586 const std::string& group,
587 group_idx_type group_idx,
588 const std::string& desc);
589
594 TreeNode(const std::string& name,
595 const std::string& group,
596 group_idx_type group_idx,
597 const std::string& desc);
598
611 const std::string& name,
612 const std::string& desc);
613
627 const std::string& group,
628 group_idx_type group_idx,
629 const std::string& desc);
630
638 TreeNode(const std::string& name,
639 const std::string& desc);
640
646 virtual ~TreeNode();
647
650
654
669 void addAlias(const std::string& alias);
670
677 void addAliases(const AliasVector& v);
678
695 void addTag(const std::string& tag);
696
703 void addTags(const std::vector<std::string>& v);
704
707
711
723 virtual std::string stringize(bool pretty=false) const {
724 (void) pretty;
725 std::stringstream ss;
726 ss << "<" << getLocation();
727 if(is_expired_){
728 ss << " EXPIRED";
729 }
730 stringizeTags(ss);
731 ss << ">";
732 return ss.str();
733 }
734
743 void stringizeTags(std::stringstream& ss) const {
744 if(tags_.size() > 0){
745 ss << " tags:[";
746 uint32_t i = 0;
747 for(auto & tag : tags_){
748 if(i != 0){
749 ss << ", ";
750 }
751 ss << *tag;
752 ++i;
753 }
754 ss << "]";
755 }
756
757 }
758
761
765
770
775 const std::string& getName() const override;
776
782 const std::string* getNamePtr() const;
783
788 bool isAnonymous() const;
789
795 bool isExpired() const;
796
801 bool isIndexableByGroup() const;
802
808 const std::string& getGroup() const;
809
817 const std::string* getGroupNamePtr() const;
818
825
839 const std::vector<const std::string*>& getTags() const;
840
844 bool hasTag(const std::string& tag) const;
845
853 bool hasTag(const std::string* interned_tag_name) const;
854
859 const std::string& getDesc() const;
860
865 bool isBuiltin() const;
866
872 void markHidden(bool hidden=true);
873
881 bool isHidden() const;
882
885
889
902 void validateName(const std::string& nm);
903
929 void validateGroup(const std::string& name,
930 const std::string& group,
931 group_idx_type idx);
932
942 void validateDesc(const std::string& desc);
943
946
950
957 virtual bool isAttached() const {
958 return is_attached_;
959 }
960
965 virtual TreeNode* getParent() {
966 return parent_;
967 }
968
972 virtual const TreeNode* getParent() const {
973 return parent_;
974 }
975
989 template <class T, typename = typename std::enable_if<std::is_pointer<T>::value>::type>
990 const T getParentAs(bool must_exist=true) const {
991 const T result = dynamic_cast<const T>(getParent());
992 if(result == nullptr){
993 if(must_exist){
994 throw SpartaException("Could not get parent of ")
995 << getLocation() << " with type: const " << demangle(typeid(T*).name());
996 }
997 return nullptr;
998 }
999 return result;
1000 }
1001
1002 // Overload of getParentAs for const access with a non-pointer T type
1003 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1004 const T* getParentAs(bool must_exist=true) const {
1005 return getParentAs<const T*>(must_exist);
1006 }
1007
1008 // Overload of getParentAs for non-const access with a pointer T type
1009 template <class T, typename = typename std::enable_if<std::is_pointer<T>::value>::type>
1010 T getParentAs(bool must_exist=true) {
1011 T result = dynamic_cast<T>(getParent());
1012 if(result == nullptr){
1013 if(must_exist){
1014 throw SpartaException("Could not get parent of ")
1015 << getLocation() << " with type: const " << demangle(typeid(T*).name());
1016 }
1017 return nullptr;
1018 }
1019 return result;
1020 }
1021
1022 // Overload of getParentAs for non-const access with a non-pointer T type
1023 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1024 T* getParentAs(bool must_exist=true) {
1025 return getParentAs<T*>(must_exist);
1026 }
1027
1034 virtual TreeNode* getRoot();
1035
1039 virtual const TreeNode* getRoot() const;
1040
1045
1049 const TreeNode *getScopeRoot() const;
1050
1058
1067
1077 uint32_t getNumChildren() const;
1078
1091 TreeNode* getChildAt(uint32_t idx) const;
1092
1108
1124 uint32_t getChildren(std::vector<TreeNode*>& results,
1125 bool ignore_builtin_group=true,
1126 bool ignore_anonymous_nodes=true);
1127
1135 template <class T>
1136 uint32_t getChildrenOfType(std::vector<T*>& results) const
1137 {
1138 uint32_t orig_size = results.size();
1139 for (auto child : getChildren())
1140 {
1141 if (dynamic_cast<T*>(child))
1142 {
1143 results.emplace_back(static_cast<T*>(child));
1144 }
1145 }
1146 return results.size() - orig_size;
1147 }
1148
1154 sparta::TreeNode *findAncestorByName(const std::string &name) {
1155 sparta::TreeNode *parent = getParent();
1156 while (parent != getRoot()) {
1157 if (parent->locationMatchesPattern(name, parent->getParent())) {
1158 return parent;
1159 }
1160 parent = parent->getParent();
1161 }
1162 return nullptr;
1163 }
1164
1180 template <typename T>
1182 sparta::TreeNode *parent = getParent();
1183 while (parent != getRoot()) {
1184 if (parent->getResourceTypeRaw() == typeid(T).name()) {
1185 return parent;
1186 }
1187 parent = parent->getParent();
1188 }
1189 return nullptr;
1190 }
1191
1203 sparta::TreeNode *findAncestorByTag(const std::string& tag)
1204 {
1205 sparta::TreeNode *parent = getParent();
1206 while (parent != getRoot()) {
1207 if (parent->hasTag(tag))
1208 {
1209 return parent;
1210 }
1211 parent = parent->getParent();
1212 }
1213 return nullptr;
1214 }
1215
1225 template<typename T>
1227 {
1228 static_assert(!std::is_pointer<T>::value && !std::is_reference<T>::value,
1229 "Expected a non-pointer/non-reference T template argument");
1231 if (node)
1232 {
1233 return node->getResourceAs<T*>();
1234 }
1235 return nullptr;
1236 }
1237
1244 const AliasVector& getAliases() const;
1245
1269 uint32_t getChildrenIdentifiers(std::vector<std::string>& idents,
1270 bool ignore_builtin_group=true) const;
1271
1281 std::vector<const std::string*> getIdentifiers() const;
1282
1294 uint32_t getGroupSize(const std::string& group);
1295
1305 group_idx_type getGroupIndexMax(const std::string& group);
1306
1317 uint32_t getGroup(const std::string& group,
1318 std::vector<TreeNode*>& results);
1319
1421 uint32_t findChildren(const std::string& pattern,
1422 std::vector<TreeNode*>& results,
1423 std::vector<std::vector<std::string>>& replacements)
1424 {
1425 return findChildren_(pattern, results, replacements, false /*allow_private*/);
1426 }
1427
1431 uint32_t findChildren(const std::string& pattern,
1432 std::vector<TreeNode*>& results)
1433 {
1434 return findChildren_(pattern, results, false /*allow_private*/);
1435 }
1436
1446 virtual uint32_t findImmediateChildren_(std::regex& expr,
1447 std::vector<TreeNode*>& found,
1448 std::vector<std::vector<std::string>>& replacements,
1449 bool allow_private=false);
1450
1454 uint32_t findImmediateChildren_(std::regex& expr,
1455 std::vector<TreeNode*>& found,
1456 bool allow_private=false);
1457
1461 virtual uint32_t findImmediateChildren_(std::regex& expr,
1462 std::vector<const TreeNode*>& found,
1463 std::vector<std::vector<std::string>>& replacements,
1464 bool allow_private=false) const;
1465
1470 uint32_t findImmediateChildren_(std::regex& expr,
1471 std::vector<const TreeNode*>& found,
1472 bool allow_private=false) const;
1473
1504 bool locationMatchesPattern(const std::string& pattern,
1505 const TreeNode* pat_loc) const;
1506
1531 TreeNode* getChild(const std::string& name,
1532 bool must_exist=true)
1533 {
1534 return getChild_(name, must_exist, false /*private_also*/);
1535 }
1536
1538 const TreeNode* getChild(const std::string& name,
1539 bool must_exist=true) const
1540 {
1541 return getChild_(name, must_exist, false /*private also */);
1542 }
1543
1544
1561 std::string getDeepestMatchingPath(const std::string& path) const;
1562
1571 bool hasChild(const std::string& name) const noexcept
1572 {
1573 return hasChild_(name, false /*private also */);
1574 }
1575
1581 bool hasImmediateChild(const TreeNode* n) const noexcept;
1582
1603 template <class T,
1604 typename = typename std::enable_if<std::is_pointer<T>::value>::type,
1605 class ConstT = typename ptr_to_const_obj_ptr<T>::type>
1606 const ConstT getChildAs(const std::string& name, bool must_exist=true) const {
1607 static_assert(std::is_base_of<TreeNode, typename std::remove_pointer<T>::type>::value == true,
1608 "Cannot use getChildAs with a type argument that is not a subclass of " \
1609 "TreeNode. If the caller is looking for a resource, use " \
1610 "getChild(name)->getResource instead.");
1611 const TreeNode* child = TreeNode::getChild(name, must_exist);
1612 const ConstT result = dynamic_cast<ConstT>(child);
1613 if(result == nullptr){
1614 if(must_exist){
1615 throw SpartaException("Could not find child of \"")
1616 << getLocation() << "\" with the relative path \""
1617 << name << "\" that was of type: const "
1618 << demangle(typeid(T*).name()) << ". Found node of type "
1619 << demangle(typeid(*child).name());
1620 }
1621 return nullptr;
1622 }
1623 return result;
1624 }
1625
1626 // Overload of getChildAs for const access with a non-pointer T typeid
1627 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1628 const T* getChildAs(const std::string& name, bool must_exist=true) const {
1629 return getChildAs<const T*>(name, must_exist);
1630 }
1631
1632 // Overload of getChildAs for non-const access with a non-pointer T type
1633 template <class T, typename = typename std::enable_if<std::is_pointer<T>::value>::type>
1634 T getChildAs(const std::string& name, bool must_exist=true) {
1635 static_assert(std::is_base_of<TreeNode, typename std::remove_pointer<T>::type>::value == true,
1636 "Cannot use getChildAs with a type argument that is not a subclass of " \
1637 "TreeNode. If the caller is looking for a resource, use " \
1638 "getChild(name)->getResource instead.");
1639 TreeNode* child = TreeNode::getChild(name, must_exist);
1640 T result = dynamic_cast<T>(child);
1641 if(result == nullptr){
1642 if(must_exist){
1643 throw SpartaException("Could not find child of \"")
1644 << getLocation() << "\" with the relative path \""
1645 << name << "\" that was of type: " << demangle(typeid(T).name())
1646 << ". Found node of type "<< demangle(typeid(*child).name());
1647 }
1648 return nullptr;
1649 }
1650 return result;
1651 }
1652
1653 // Overload of getChildAs for non-const access with a non-pointer T type
1654 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1655 T* getChildAs(const std::string& name, bool must_exist=true) {
1656 return getChildAs<T*>(name, must_exist);
1657 }
1658
1659
1671 template <class T,
1672 typename = typename std::enable_if<std::is_pointer<T>::value>::type,
1673 class ConstT = typename ptr_to_const_obj_ptr<T>::type>
1674 ConstT getAs() const {
1675 static_assert(std::is_base_of<TreeNode, typename std::remove_pointer<T>::type>::value == true,
1676 "Cannot use getAs with a type argument that is not a subclass of " \
1677 "TreeNode.");
1678 ConstT result = dynamic_cast<typename ptr_to_const_obj_ptr<T>::type>(this);
1679 if(result == nullptr){
1680 throw SpartaException("Could not get TreeNode \"")
1681 << getLocation() << "\" as type: const " << demangle(typeid(T).name());
1682 }
1683 return result;
1684 }
1685
1696 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1697 const T* getAs() const {
1698 return getAs<const T*>();
1699 }
1700
1711 template <class T, typename = typename std::enable_if<std::is_pointer<T>::value>::type>
1712 T getAs() {
1713 static_assert(std::is_base_of<TreeNode, typename std::remove_pointer<T>::type>::value == true,
1714 "Cannot use getAs with a type argument that is not a subclass of " \
1715 "TreeNode.");
1716 T result = dynamic_cast<T>(this);
1717 if(result == nullptr){
1718 throw SpartaException("Could not get TreeNode \"")
1719 << getLocation() << "\" as type: " << demangle(typeid(T).name());
1720 }
1721 return result;
1722 }
1723
1734 template <class T, typename = typename std::enable_if<!std::is_pointer<T>::value>::type>
1735 T* getAs() {
1736 return getAs<T*>();
1737 }
1738
1756 uint32_t findChildrenByTag(const std::string& tag,
1757 std::vector<TreeNode*>& results,
1758 int32_t max_depth=-1);
1759
1773 bool isDescendantOf(const TreeNode* ancestor,
1774 int32_t max_depth=-1) const;
1775
1779 std::string getLocation() const override final;
1780
1796 std::string getDisplayLocation() const;
1797
1804 std::string getExpectedLocation() const;
1805
1830 std::string renderSubtree(int32_t max_depth=-1,
1831 bool show_builtins=false,
1832 bool names_only=false,
1833 bool hide_hidden=false,
1834 bool(*leaf_filt_fxn)(const TreeNode*) = nullptr) const;
1835
1846 uint32_t getLevel() const;
1847
1853 template <typename T>
1854 uint32_t getRecursiveNodeCount() const {
1855 uint32_t count = dynamic_cast<const typename std::remove_const<typename std::remove_pointer<T>::type>::type*>(this) != nullptr;
1856 for(auto& child : children_){
1857 count += child->getRecursiveNodeCount<T>();
1858 }
1859 return count;
1860 }
1861
1875
1878
1882
1887 {
1888 public:
1890 virtual ~ExtensionsBase();
1891 virtual void setParameters(std::unique_ptr<ParameterSet> params) = 0;
1892 virtual ParameterSet * getParameters() = 0;
1893 virtual ParameterSet * getYamlOnlyParameters() = 0;
1894 virtual void postCreate() {}
1895 };
1896
1900 void addExtensionParameters(const std::string & extension_name,
1901 std::unique_ptr<ParameterSet> extension_params);
1902
1908 void addExtensionFactory(const std::string & extension_name,
1909 std::function<ExtensionsBase*()> factory);
1910
1917 ExtensionsBase * getExtension(const std::string & extension_name);
1918
1926
1935 const std::set<std::string> & getAllExtensionNames();
1936
1940 size_t getNumExtensions() const {
1941 return extensions_.size();
1942 }
1943
1947
1951
1987 void addChild(TreeNode* child, bool inherit_phase=true);
1988
1994 void addChild(TreeNode& child);
1995
2008 {
2009 incrementPrivacyLevel_(1);
2010 }
2011
2016 {
2017 is_scope_root_ = true;
2018 }
2019
2020
2024 bool isScopeRoot() const
2025 {
2026 return is_scope_root_;
2027 }
2028
2031
2040 const Clock* getClock() override{
2041 if(isFinalized()){
2042 return working_clock_;
2043 }else{
2044 // Search for clock
2045 TreeNode* n = this;
2046 while(n){
2047 const Clock* c = n->getLocalClock();
2048 if(c){
2049 return c;
2050 }
2051 n = n->getParent();
2052 }
2053 return nullptr;
2054 }
2055 }
2056
2060 const Clock* getClock() const {
2061 if(isFinalized()){
2062 return working_clock_;
2063 }else{
2064 // Search for clock
2065 const TreeNode* n = this;
2066 while(n){
2067 const Clock* c = n->getLocalClock();
2068 if(c){
2069 return c;
2070 }
2071 n = n->getParent();
2072 }
2073 return nullptr;
2074 }
2075 }
2076
2091 return clock_;
2092 }
2093
2097 const Clock* getLocalClock() const {
2098 return clock_;
2099 }
2100
2111 virtual void setClock(const Clock * clk);
2112
2116 Scheduler * getScheduler(const bool must_exist = false);
2117 const Scheduler * getScheduler(const bool must_exist = false) const;
2118
2141
2146
2162 virtual void addLink(TreeNode *node, const std::string &label);
2163
2177 virtual void activateLink(const std::string &label);
2178
2189 static std::string createSearchRegexPattern(const std::string& pat);
2190
2199 static bool hasWildcardCharacters(const std::string& name);
2200
2216 static std::string getNextName(const std::string& name, size_t& pos);
2217
2226 static bool matchesGlobLike(const std::string& pattern, const std::string& other);
2227
2228
2229 private:
2234 void lockdownParametersUtil_(){
2235 for(auto child : children_){
2236 child->lockdownParametersUtil_();
2237 }
2238 special_params_lockdown_ = true;
2239 }
2240
2246 static node_uid_type getNextNodeUID_();
2247
2255 static void trackParentlessNode_(TreeNode* node);
2256
2265 static void untrackParentlessNode_(TreeNode* node);
2266
2279 static void trackNode_(TreeNode* node);
2280
2302 static void untrackNode_(TreeNode* node) noexcept;
2303
2311 void informAddedChildSubtree_();
2312
2322 void informAddedChildAncestors_(TreeNode* des);
2323
2330 void incrementGetChildCount_(const std::string& name) const;
2331
2335
2363 virtual void setParent_(TreeNode* parent, bool inherit_phase);
2371 void addChild_(TreeNode* child, bool inherit_phase);
2385 void recursSetPhase_(TreePhase phase);
2386
2389
2393
2402 void getLocation_(std::stringstream& ss, bool anticipate_parent=false) const;
2403
2408 void getDisplayLocation_(std::stringstream& ss) const;
2409
2425 uint32_t renderSubtree_(std::stringstream& ss,
2426 uint32_t indent,
2427 int32_t max_depth,
2428 bool show_builtins,
2429 bool names_only,
2430 bool hide_hidden,
2431 bool(*leaf_filt_fxn)(const TreeNode*)) const;
2432
2442 virtual TreeNode*
2443 getImmediateChildByIdentity_(const std::string& name,
2444 bool must_exist=true)
2445 ;
2446
2447 // Overload of getImmediateChildByIdentity_
2449 virtual const TreeNode*
2450 getImmediateChildByIdentity_(const std::string& name,
2451 bool must_exist=true)
2452 const;
2460 void ensureNoParent_(const char* action);
2461
2466 OneWayBool<false> special_params_lockdown_;
2467
2470
2471 protected:
2472
2481 static bool identityMatchesPattern_(const std::string& ident,
2482 std::regex& expr,
2483 std::vector<std::string>& replacements);
2484
2485
2489 static bool identityMatchesPattern_(const std::string& ident,
2490 std::regex& expr);
2491
2511 static std::string getPreviousName_(const std::string& name,
2512 size_t& pos);
2513
2520 std::pair<uint32_t, std::string> recursGetDeepestMatchingPath_(const std::string& path,
2521 size_t name_pos) const;
2522
2553 void setExpectedParent_(const TreeNode* parent);
2554
2561
2576
2584
2592
2599 void enterConfig_() noexcept;
2600
2607
2614
2631
2653
2677 void dumpDebugContent_(std::ostream& out) const noexcept;
2678
2679
2688 void enterTeardown_() noexcept;
2689
2701 void verifyUniqueChildIdentifier_(const std::string& ident,
2702 bool ignore_group_collision=false);
2703
2724
2733
2739
2745
2754 return special_params_lockdown_;
2755 }
2756
2760
2769 {
2770 public:
2771
2772 typedef void (*stub_type)(void* obj,
2773 const TreeNode& origin,
2774 const TreeNode* obs_pt,
2775 const void* data); //, const std::type_info& tinfo);
2776
2777 delegate() :
2778 object_ptr(0),
2779 obs_point(0),
2780 name_ptr(0),
2781 stub_ptr(0),
2782 reveals_origin(true)
2783 { }
2784
2785 delegate(const delegate&& d) :
2786 object_ptr(d.object_ptr),
2787 obs_point(d.obs_point),
2788 name_ptr(d.name_ptr),
2789 stub_ptr(d.stub_ptr),
2790 reveals_origin(d.reveals_origin)
2791 { }
2792
2797 object_ptr = d.object_ptr;
2798 obs_point = d.obs_point;
2799 name_ptr = d.name_ptr;
2800 stub_ptr = d.stub_ptr;
2801 reveals_origin = d.reveals_origin;
2802
2803 return *this;
2804 }
2805
2806 delegate(const delegate& d) :
2807 object_ptr(d.object_ptr),
2808 obs_point(d.obs_point),
2809 name_ptr(d.name_ptr),
2810 stub_ptr(d.stub_ptr),
2811 reveals_origin(d.reveals_origin)
2812 { }
2813
2814
2823 template <class DataT, class T, void (T::*TMethod)(const TreeNode&,
2824 const TreeNode&,
2825 const DataT&)>
2826 constexpr bool equals(T* obj,
2827 const TreeNode& obs_pt,
2828 const std::string& name) const
2829 {
2830 return (stub_ptr == &method_stub<DataT, T, TMethod>)
2831 && (obj == object_ptr)
2832 && (&obs_pt == obs_point)
2833 && (name == *name_ptr);
2834 }
2835
2836 template <class DataT, class T, void (T::*TMethod)(const DataT&)>
2837 constexpr bool equals(T* obj,
2838 const TreeNode& obs_pt,
2839 const std::string& name) const
2840 {
2841 return (stub_ptr == &method_stub<DataT, T, TMethod>)
2842 && (obj == object_ptr)
2843 && (&obs_pt == obs_point)
2844 && (name == *name_ptr);
2845 }
2846
2847
2855 bool operator==(const delegate& d) const {
2856 return (stub_ptr == d.stub_ptr)
2857 && (object_ptr == d.object_ptr)
2858 && (obs_point == d.obs_point)
2859 && (name_ptr == d.name_ptr);
2860 }
2861
2880 bool observes(const TreeNode& obs_pt, const std::string* name) const
2881 {
2882 return (&obs_pt == obs_point)
2883 && TreeNode::notificationCategoryMatch(name_ptr, name);
2884 }
2885
2892 template <class DataT, class T, void (T::*TMethod)(const TreeNode&,
2893 const TreeNode&,
2894 const DataT&)>
2895 static delegate from_method(T* obj,
2896 const TreeNode& obs_pt,
2897 const std::string& name)
2898 {
2899 delegate d;
2900 d.object_ptr = obj;
2901 d.obs_point = &obs_pt;
2902 d.name_ptr = StringManager::getStringManager().internString(name);
2903 d.stub_ptr = &method_stub<DataT, T, TMethod>;
2904 return d;
2905 }
2906
2907 template <class DataT, class T, void (T::*TMethod)(const DataT&)>
2908 static delegate from_method(T* obj,
2909 const TreeNode& obs_pt,
2910 const std::string& name)
2911 {
2912 delegate d;
2913 d.object_ptr = obj;
2914 d.obs_point = &obs_pt;
2915 d.name_ptr = StringManager::getStringManager().internString(name);
2916 d.stub_ptr = &method_stub<DataT, T, TMethod>;
2917 d.reveals_origin = false;
2918 return d;
2919 }
2920
2924 template <typename DataT>
2925 void operator()(const TreeNode& origin,
2926 const DataT& data) const
2927 {
2928 (*stub_ptr)(object_ptr, origin, obs_point, &data); //, typeid(DataT));
2929 }
2930
2931 const std::string* getNameID() const {
2932 return name_ptr;
2933 }
2934
2935 const TreeNode* getObservationPoint() const {
2936 return obs_point;
2937 }
2938
2939 bool revealsOrigin() const { return reveals_origin; }
2940
2941 private:
2942
2949 template <class DataT, class T, void (T::*TMethod)(const TreeNode&,
2950 const TreeNode&,
2951 const DataT&)>
2952 static void method_stub(void* obj,
2953 const TreeNode& origin,
2954 const TreeNode* obs_pt,
2955 const void* data)
2956 {
2957 // Check type
2958 //sparta_assert(tinfo == typeid(DataT),
2959 // "Expected to invoke method delegate for data type \"" << typeid(DataT).name()
2960 // << "\" with incorrect data type \"" << typeid(tinfo).name() << "\"")
2961
2962 T* p = static_cast<T*>(obj);
2963 const DataT& d = *static_cast<const DataT*>(data);
2964 return (p->*TMethod)(origin, *obs_pt, d);
2965 }
2966
2967 template <class DataT, class T, void (T::*TMethod)(const DataT&)>
2968 static void method_stub(void* obj,
2969 const TreeNode& origin,
2970 const TreeNode* obs_pt,
2971 const void* data)
2972 {
2973 (void) origin;
2974 (void) obs_pt;
2975 T* p = static_cast<T*>(obj);
2976 const DataT& d = *static_cast<const DataT*>(data);
2977 return (p->*TMethod)(d);
2978 }
2979
2980 template <class DataT, void (*TMethod)(const TreeNode&,
2981 const TreeNode&,
2982 const DataT&)>
2983 static void method_stub(void* obj,
2984 const TreeNode& origin,
2985 const TreeNode* obs_pt,
2986 const void* data)
2987 {
2988 (void) obj;
2989 const DataT& d = *static_cast<const DataT*>(data);
2990 return (*TMethod)(origin, *obs_pt, d);
2991 }
2992
2993 template <class DataT, void (*TMethod)(const DataT&)>
2994 static void method_stub(void* obj,
2995 const TreeNode& origin,
2996 const TreeNode* obs_pt,
2997 const void* data)
2998 {
2999 (void) obj;
3000 (void) origin;
3001 (void) obs_pt;
3002 const DataT& d = *static_cast<const DataT*>(data);
3003 return (*TMethod)(d);
3004 }
3005
3010 void* object_ptr;
3011
3015 const TreeNode* obs_point;
3016
3021 const std::string* name_ptr;
3022
3026 stub_type stub_ptr;
3027
3033 bool reveals_origin = true;
3034 };
3035
3043
3044 const std::type_info* tinfo_;
3045 size_t hash_code_;
3046
3047 public:
3048
3049 type_info_container() = delete;
3050
3052 tinfo_(rhp.tinfo_),
3053 hash_code_(rhp.hash_code_)
3054 { }
3055
3056 type_info_container(const std::type_info& tinfo) :
3057 tinfo_(&tinfo),
3058 hash_code_(tinfo.hash_code())
3059 { }
3060
3061 bool operator==(const type_info_container& rhp) const {
3062 return hash_code_ == rhp.hash_code_;
3063 }
3064
3065 bool operator<(const type_info_container& rhp) const {
3066 return hash_code_ < rhp.hash_code_;
3067 }
3068
3069 const std::type_info& operator*() const {
3070 return *tinfo_;
3071 }
3072
3073 const std::type_info* get() const {
3074 return tinfo_;
3075 }
3076 };
3077
3081 typedef std::vector<delegate> DelegateVector;
3082
3086 typedef std::map<type_info_container, DelegateVector> NotificationObserverMap;
3087
3088
3097 template <typename DataT>
3099 const DataT& data,
3100 const std::string* name_id) {
3101 // Assure that this notification passes canGenerateNotification. It
3102 // is of no use to us if nodes are generating Notifications that no
3103 // observer can possible expect by examining the tree.
3104 // Skip this in production builds for performance
3105#ifndef NDEBUG
3106 sparta_assert(origin);
3107 sparta_assert(name_id);
3108 NotificationInfo info(origin, &typeid(DataT), name_id);
3109 if(!canGenerateNotification(info)){
3110 throw SpartaException("TreeNode ")
3111 << getLocation() << " posted a notification <"
3112 << origin->getLocation() << ", \"" << demangle(typeid(DataT).name())
3113 << "\", \"" << *name_id
3114 << "\"> which it did not properly announce through canGenerateNotification";
3115 }
3116#endif
3117 propagateNotification_(origin, data, name_id);
3118
3119 // Post to the global virtual node
3120 getVirtualGlobalNode()->propagateNotification_(origin, data, name_id);
3121 }
3122
3138 template <typename DataT, typename T, void (T::*TMethod)(const TreeNode&,
3139 const TreeNode&,
3140 const DataT&)>
3141 DelegateVector::iterator findDelegate_(DelegateVector& dvec,
3142 T* obj,
3143 const std::string& target_name) {
3144 const DelegateVector::const_iterator dend = dvec.end();
3145 DelegateVector::iterator d;
3146 for(d=dvec.begin(); d!=dend; ++d){
3147 if(d->equals<DataT, T, TMethod>(obj, *this, target_name)){
3148 break;
3149 }
3150 }
3151 return d;
3152 }
3153
3154 // Overload of findDelegate_ with one TMethod signature having a sole DataT parameter
3155 template <typename DataT, typename T, void (T::*TMethod)(const DataT&)>
3156 DelegateVector::iterator findDelegate_(DelegateVector& dvec,
3157 T* obj,
3158 const std::string& target_name) {
3159 const DelegateVector::const_iterator dend = dvec.end();
3160 DelegateVector::iterator d;
3161 for(d=dvec.begin(); d!=dend; ++d){
3162 if(d->equals<DataT, T, TMethod>(obj, *this, target_name)){
3163 break;
3164 }
3165 }
3166 return d;
3167 }
3168
3190 virtual void
3192 const std::vector<const std::string*>& name_ids,
3193 TreeNode* obs_node,
3194 const delegate* del,
3195 const bool allow_private);
3196
3209 virtual void
3211 const std::vector<const std::string*>& name_ids,
3212 TreeNode* obs_node,
3213 const delegate* del,
3214 const bool allow_private);
3215
3220 void
3222 const std::string& name,
3223 TreeNode* obs_node,
3224 const delegate* del,
3225 const bool private_only)
3226 {
3227 auto names = parseNotificationNameString(name);
3228 broadcastRegistrationForNotificationToChildren_(tinfo, names, obs_node, del,
3229 private_only);
3230 }
3231
3236 void
3238 const std::string& name,
3239 TreeNode* obs_node,
3240 const delegate* del,
3241 const bool private_only)
3242 {
3243 auto names = parseNotificationNameString(name);
3244 broadcastDeregistrationForNotificationToChildren_(tinfo, names, obs_node, del,
3245 private_only);
3246 }
3247
3256 template <typename DataT>
3258 const DataT& data,
3259 const std::string* name_id) {
3260 to_invoke->invokeDelegates_(this, data, name_id);
3261 }
3262
3263 private:
3264
3276 template <typename DataT>
3277 void invokeDelegates_(const TreeNode* origin,
3278 const DataT& data,
3279 const std::string* name_id) {
3280 auto itr = obs_local_.find(typeid(DataT));
3281 if(itr != obs_local_.end()){
3282 DelegateVector& observers = itr->second;
3283 for(delegate& d : observers) {
3284 // Invoke delegate if matched
3285 if(d.getNameID() == name_id
3286 || d.getNameID() == StringManager::getStringManager().EMPTY){
3287 d(*origin, data); // invoke
3288 }
3289 }
3290 }
3291 }
3292
3311 template <typename DataT>
3312 void propagateNotification_(const TreeNode* origin,
3313 const DataT& data,
3314 const std::string* name_id) {
3315
3316 invokeDelegates_<DataT>(origin, data, name_id);
3317
3318 if(getParent() != nullptr){
3319 getParent()->propagateNotification_(origin, data, name_id);
3320 }
3321 }
3322
3323 // Internal Notification System
3326
3327 public:
3328
3332
3340
3343 const std::type_info* _tinfo,
3344 const std::string* _name) :
3345 origin(_origin),
3346 tinfo(_tinfo),
3347 name(_name)
3348 {
3349 checkValid();
3350 }
3351
3354 origin(rhp.origin),
3355 tinfo(rhp.tinfo),
3356 name(rhp.name)
3357 {
3358 checkValid();
3359 }
3360
3363 origin(rhp.origin),
3364 tinfo(rhp.tinfo),
3365 name(rhp.name)
3366 {
3367 checkValid();
3368 }
3369
3372 rhp.checkValid();
3373 origin = rhp.origin;
3374 tinfo = rhp.tinfo;
3375 name = rhp.name;
3376 return *this;
3377 }
3378
3382 void checkValid() const {
3383 sparta_assert(origin);
3384 sparta_assert(tinfo);
3385 sparta_assert(name);
3386 }
3387
3392
3396 const std::type_info* tinfo;
3397
3401 const std::string* name;
3402 };
3403
3413 uint32_t getPossibleNotifications(std::vector<NotificationInfo>& infos) const;
3414
3420 void dumpPossibleNotifications(std::ostream& o) const noexcept;
3421
3450 template <typename DataT=ANY_TYPE>
3451 uint32_t locateNotificationSources(std::vector<TreeNode*>& nodes,
3452 const std::string& name="") {
3453 static_assert(std::is_same<
3454 typename std::remove_cv<
3455 typename std::remove_reference<
3456 typename std::remove_pointer<DataT>::type
3457 >::type
3458 >::type,
3459 DataT
3460 >::value,
3461 "DataT must NOT be a const, volatile, pointer, or reference"
3462 "type. It violates at least one of these restrictions");
3463
3464 auto& strmgr = StringManager::getStringManager();
3465 const std::string* name_id = strmgr.internString(name);
3466 return locateNotificationSources_<DataT>(nodes, name_id);
3467 }
3468
3476 template <typename DataT=ANY_TYPE>
3477 void dumpLocatedNotificationSources(std::ostream& o, const std::string& name=""){
3478 std::vector<TreeNode*> nodes;
3480 for(const TreeNode* n : nodes){
3481 o << n->stringize() << std::endl;
3482 }
3483 }
3484
3494 uint32_t getPossibleSubtreeNotifications(std::vector<NotificationInfo>& infos) const noexcept;
3500 void dumpPossibleSubtreeNotifications(std::ostream& o) const noexcept;
3501
3526 bool canGenerateNotification(const std::type_info& tinfo,
3527 const std::string* name) const;
3528
3538 bool canGenerateNotification(const std::type_info& tinfo,
3539 const std::string& name) const;
3540
3547
3573 bool canSubtreeGenerateNotification(const std::type_info& tinfo,
3574 const std::string* name) const;
3575
3585 bool canSubtreeGenerateNotification(const std::type_info& tinfo,
3586 const std::string& name) const;
3587
3592 bool canSubtreeGenerateNotifications(const std::type_info& tinfo,
3593 const std::vector<const std::string*>& names) const;
3594
3602 static std::vector<const std::string*> parseNotificationNameString(const std::string& csl);
3603
3677 template <typename DataT, typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const DataT&)>
3678 void registerForNotification(T* obj, const std::string& name, bool ensure_possible=true)
3679 {
3680 registerForNotification_<DataT, T, TMethod>(obj, name, ensure_possible, false /*allow_private*/);
3681 }
3682
3683 // Overload which allows registration with a class member function accepting only a data argument
3684 template <typename DataT, typename T, void (T::*TMethod)(const DataT&)>
3685 void registerForNotification(T* obj, const std::string& name, bool ensure_possible=true)
3686 {
3687 registerForNotification_<DataT, T, TMethod>(obj, name, ensure_possible, false /*allow_private*/);
3688 }
3689
3699 template <typename DataT, typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const DataT&)>
3700 void deregisterForNotification(T* obj, const std::string& name)
3701 {
3702 deregisterForNotification_<DataT, T, TMethod>(obj, name, false /* allow_private */);
3703 }
3704
3705 // Overload which allows deregistration with a class member function accepting only a data argument
3706 template <typename DataT, typename T, void (T::*TMethod)(const DataT&)>
3707 void deregisterForNotification(T* obj, const std::string& name)
3708 {
3709 deregisterForNotification_<DataT, T, TMethod>(obj, name, false /* allow_private */);
3710 }
3711
3719 bool hasObserversRegisteredForNotification(const std::type_info& tinfo,
3720 const std::string* name) const noexcept;
3721
3731 void getDelegatesRegisteredForNotification(const std::type_info& tinfo,
3732 const std::string* name,
3733 std::vector<delegate>& dels) noexcept;
3734
3741 static bool notificationCategoryMatch(const std::string* query_id,
3742 const std::string* node_id);
3743
3744 // Public Notification System
3747
3748 private:
3749
3753 void incrementPrivacyLevel_(uint32_t privacy_increment)
3754 {
3755 privacy_level_ += privacy_increment;
3756 for (auto n : children_)
3757 {
3758 n->incrementPrivacyLevel_(privacy_increment);
3759 }
3760 }
3761
3782 virtual void onAddingChild_(TreeNode* child) {
3783 (void) child;
3784 // No actions by default
3785 // Could throw to reject child
3786 }
3787
3810 virtual void onSettingParent_(const TreeNode* parent) const {
3811 (void) parent;
3812 // No actions by default
3813 // Could throw to reject parent
3814 }
3815
3832 virtual void onAddedAsChild_() noexcept {
3833 }
3834
3847 virtual void onDescendentSubtreeAdded_(TreeNode* des) noexcept {
3848 (void) des;
3849 }
3850
3857 virtual void onDestroyingParent_() noexcept {
3858 }
3859
3867 virtual void onDestroyingChild_(TreeNode* child) noexcept {
3868 (void) child;
3869 }
3870
3874 virtual void onConfiguring_() {;}
3875
3879 virtual void onBindTreeEarly_() {;}
3880
3884 virtual void onBindTreeLate_() {;}
3885
3914 virtual void onEnteringTeardown_() noexcept {
3915 }
3916
3931 void addChildNameMapping_(const std::string& name,
3932 TreeNode* child);
3933
3938 template <typename DataT>
3939 uint32_t locateNotificationSources_(std::vector<TreeNode*>& nodes, const std::string* name_id){
3940 uint32_t additions = 0;
3941
3942 const std::string* dummy;
3943 if(canGenerateNotification_(typeid(DataT), name_id, dummy)){
3944 nodes.push_back(this);
3945 ++additions;
3946 }
3947
3948 for(TreeNode* child : children_){
3949 additions += child->template locateNotificationSources_<DataT>(nodes, name_id);
3950 }
3951 return additions;
3952 }
3953
3979 virtual void notificationObserverAdded_(const std::type_info& tinfo,
3980 const std::string* name_id,
3981 TreeNode* obs_node,
3982 const delegate* del) {
3983 (void) tinfo;
3984 (void) name_id;
3985 (void) obs_node;
3986 (void) del;
3987 }
3988
3989
4008 virtual void notificationObserverRemoved_(const std::type_info& tinfo,
4009 const std::string* name_id,
4010 TreeNode* obs_node,
4011 const delegate* del) {
4012 (void) tinfo;
4013 (void) name_id;
4014 (void) obs_node;
4015 (void) del;
4016 }
4017
4046 virtual bool canGenerateNotification_(const std::type_info& tinfo,
4047 const std::string* name,
4048 const std::string*& match) const {
4049 (void) tinfo;
4050 (void) name;
4051 (void) match;
4052 return false;
4053 }
4054
4066 virtual void getPossibleNotifications_(std::vector<NotificationInfo>& infos) const {
4067 (void) infos;
4068 }
4069
4080 virtual void createResource_() {
4081 sparta_assert(isFinalizing()); // Must be in the finalizing phase
4082 }
4083
4094 virtual void validateNode_() const {
4095 }
4096
4104 bool canSeeChild_(const TreeNode* node) const
4105 {
4106 sparta_assert(node != nullptr);
4107 // If the node is not on the same privacy level then we can't see it.
4108 return (privacy_level_ == node->privacy_level_);
4109 }
4110 uint32_t findChildren_(const std::string& pattern,
4111 std::vector<TreeNode*>& results,
4112 std::vector<std::vector<std::string>>& replacements,
4113 bool allow_private);
4114
4118 uint32_t findChildren_(const std::string& pattern,
4119 std::vector<TreeNode*>& results,
4120 bool allow_private);
4125 template <typename DataT, typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const DataT&)>
4126 void registerForNotification_(T* obj, const std::string& name, bool ensure_possible=true, bool allow_private=false)
4127 {
4128 (void)allow_private;
4129 const std::type_info& data_type = typeid(DataT);
4130 if(true == ensure_possible && false == canSubtreeGenerateNotification(data_type, name)){
4131 throw SpartaException("Cannot registerForNotification for data type \"")
4132 << demangle(typeid(DataT).name()) << "\" and name=\"" << name << "\" on node " << getLocation()
4133 << " with callback on \"" << demangle(typeid(T).name()) << "\""
4134 << "\" because this notification cannot possibly be generated by any descendant of this "
4135 << "node. Set ensure_possible=false to prevent this check if additional notification "
4136 << "source descendants are expected to be added. "
4137 << "It is possible the node generating the desired notification is in a private sub tree.";
4138 }
4139
4140 DelegateVector& observers = obs_local_[data_type]; // Create notification map
4141 if(findDelegate_<DataT, T, TMethod>(observers, obj, name) != observers.end()){
4142 throw SpartaException("Already observing a notification for data type \"")
4143 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4144 << " with callback on \"" << demangle(typeid(T).name()) << "\""
4145 << "\". Cannot register";
4146 }
4147
4148 delegate d = delegate::from_method<DataT, T, TMethod>(obj, *this, name);
4149 observers.push_back(std::move(d));
4150
4151 // Let children know
4152 broadcastRegistrationForNotificationListStringToChildren_(typeid(DataT), name, this, &observers.back(), allow_private);
4153 }
4154
4155 // Overload which allows registration with a class member function accepting only a data argument
4156 template <typename DataT, typename T, void (T::*TMethod)(const DataT&)>
4157 void registerForNotification_(T* obj, const std::string& name, bool ensure_possible=true, const bool allow_private=false)
4158 {
4159 (void)allow_private;
4160 const std::type_info& data_type = typeid(DataT);
4161 if(true == ensure_possible && false == canSubtreeGenerateNotification(data_type, name)){
4162 throw SpartaException("Cannot registerForNotification for data type \"")
4163 << demangle(typeid(DataT).name()) << "\" and name=\"" << name << "\" on node " << getLocation()
4164 << " with callback on \"" << demangle(typeid(T).name()) << "\""
4165 << "\" because this notification cannot possibly be generated by any descendant of this "
4166 << "node. Set ensure_possible=false to prevent this check if additional notification "
4167 << "source descendants are expected to be added. "
4168 << "It is possible the node generating the desired notification is in a private sub tree.";
4169 }
4170
4171 DelegateVector& observers = obs_local_[data_type]; // Create notification map
4172 if(findDelegate_<DataT, T, TMethod>(observers, obj, name) != observers.end()){
4173 throw SpartaException("Already observing a notification for data type \"")
4174 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4175 << " with callback on \"" << demangle(typeid(T).name()) << "\""
4176 << "\". Cannot register";
4177 }
4178
4179 delegate d = delegate::from_method<DataT, T, TMethod>(obj, *this, name);
4180 observers.push_back(std::move(d));
4181
4182 // Let children know
4183 broadcastRegistrationForNotificationListStringToChildren_(typeid(DataT), name, this, &observers.back(), allow_private);
4184 }
4185
4190 template <typename DataT, typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const DataT&)>
4191 void deregisterForNotification_(T* obj, const std::string& name, const bool allow_private)
4192 {
4193 (void)allow_private;
4194 const std::type_info& data_type = typeid(DataT);
4195 auto itr = obs_local_.find(data_type);
4196 if(itr == obs_local_.end()){
4197 throw SpartaException("Not currently observing any notification for data type \"")
4198 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4199 << " with callback on \"" << demangle(typeid(T).name()) << "\" function \"" << TMethod
4200 << "\". Cannot deregister";
4201 }
4202 DelegateVector& observers = itr->second;
4203 DelegateVector::iterator d = findDelegate_<DataT, T, TMethod>(observers, obj, name);
4204 if(observers.end() == d){
4205 throw SpartaException("Not currently observing a notification for data type \"")
4206 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4207 << " . Attempted to deregister \"" << demangle(typeid(T).name()) << "\" function \"" << TMethod
4208 << "\". Cannot deregister";
4209 }
4210
4211 // Let children know that a delegate has been deregistered
4212 broadcastDeregistrationForNotificationListStringToChildren_(data_type, name, this, &(*d), allow_private);
4213
4214 observers.erase(d);
4215 }
4216 // Overload which allows deregistration with a class member function accepting only a data argument
4217 template <typename DataT, typename T, void (T::*TMethod)(const DataT&)>
4218 void deregisterForNotification_(T* obj, const std::string& name, const bool allow_private)
4219 {
4220 (void)allow_private;
4221 const std::type_info& data_type = typeid(DataT);
4222 auto itr = obs_local_.find(data_type);
4223 if(itr == obs_local_.end()){
4224 throw SpartaException("Not currently observing any notification for data type \"")
4225 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4226 << " with callback on \"" << demangle(typeid(T).name()) << "\" function \"" << TMethod
4227 << "\". Cannot deregister";
4228 }
4229 DelegateVector& observers = itr->second;
4230 DelegateVector::iterator d = findDelegate_<DataT, T, TMethod>(observers, obj, name);
4231 if(observers.end() == d){
4232 throw SpartaException("Not currently observing a notification for data type \"")
4233 << demangle(typeid(DataT).name()) << "\" Name \"" << name << "\" on node " << getLocation()
4234 << " . Attempted to deregister \"" << demangle(typeid(T).name()) << "\" function \"" << TMethod
4235 << "\". Cannot deregister";
4236 }
4237
4238 // Let children know that a delegate has been deregistered
4239 broadcastDeregistrationForNotificationListStringToChildren_(data_type, name, this, &(*d), allow_private);
4240
4241 observers.erase(d);
4242 }
4247 const TreeNode::ChildrenVector& getAllChildren_() const
4248 {
4249 return children_;
4250 }
4251
4255 template <typename T> T *getScopeRootImpl_(T *node) const;
4256
4260 TreeNode* getChild_(const std::string& name,
4261 bool must_exist,
4262 bool private_also);
4263
4265 const TreeNode* getChild_(const std::string& name,
4266 bool must_exist,
4267 bool private_also) const;
4268
4273 bool hasChild_(const std::string& name, bool private_also) const noexcept;
4274
4275 private:
4276
4280 const node_uid_type node_uid_;
4281
4285 const std::string* name_;
4286
4290 const bool anon_;
4291
4297 const bool is_indexable_;
4298
4303 const std::string * const group_ptr_;
4304
4308 const group_idx_type group_idx_;
4309
4315 std::vector<const std::string*> tags_;
4316
4320 const std::string * const desc_ptr_;
4321
4334 const std::string* parent_loc_;
4335
4339 TreeNode* parent_;
4340
4345 bool is_attached_;
4346
4351 const Clock* clock_;
4352
4359 const Clock* working_clock_;
4360
4365 std::unordered_map<std::string, std::unique_ptr<ExtensionsBase>> extensions_;
4366 std::unordered_map<std::string, std::unique_ptr<ParameterSet>> extension_parameters_;
4367 std::unordered_map<std::string, std::function<ExtensionsBase*()>> extension_factories_;
4368 std::set<std::string> extension_names_;
4369 ExtensionDescriptorVec extension_descs_;
4370
4374
4379 mutable uint32_t num_children_finds_;
4380
4386 mutable uint32_t num_children_gets_;
4387
4390
4396 const TreeNode* expected_parent_;
4397
4401 bool is_builtin_;
4402
4407 bool is_hidden_;
4408
4412 AliasVector aliases_;
4413
4418 SharedPtr self_ptr_;
4419
4429 ChildrenVector children_;
4430
4435 ChildNameMapping names_;
4436
4443 NotificationObserverMap obs_local_;
4444
4449 bool is_expired_;
4450
4482 uint32_t privacy_level_ = 0;
4483
4495 bool is_scope_root_ = false;
4496
4503 class TreeNodeStatics {
4504 public:
4509 std::map<const TreeNode*, WeakPtr> parentless_map_;
4510
4523 std::map<const TreeNode*, WeakPtr> node_map_;
4524 };
4525 static TreeNodeStatics *statics_;
4526
4532 static node_uid_type next_node_uid_;
4533
4537 static TagsMap global_tags_map_;
4538
4543 static uint32_t teardown_errors_;
4544 };
4545
4547 template<class Ch,class Tr>
4548 inline std::basic_ostream<Ch,Tr>&
4549 operator<< (std::basic_ostream<Ch,Tr>& out, sparta::TreeNode const & tn) {
4550 out << tn.stringize();
4551 return out;
4552 }
4553
4555 inline std::ostream& operator<< (std::ostream& out, sparta::TreeNode const * tn) {
4556 if(nullptr == tn){
4557 out << "null";
4558 }else{
4559 out << tn->stringize();
4560 }
4561 return out;
4562 }
4563} // namespace sparta
Contains a number of ArchData pointers.
Basic Node framework in sparta device tree composite pattern.
Helpers for printing and populating vectors.
Object with a name which holds a Resource.
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Helpers for enforcing StaticInitialization order.
Container class for any number of ArchData pointers owned externally.
Manages building a clock tree.
A representation of simulated time.
Definition Clock.hpp:44
Generic container of Parameters.
virtual bool isFinalizing() const
Is this node (and thus the entire tree above it) "finalized".
virtual bool isFinalized() const
Is this node (and thus the entire tree above it) "finalized".
TreePhase getPhase() const
Gets the trees current phase.
TreePhase
Current phase of tree construction (applies to node and entire tree).
@ TREE_CONFIGURING
Setting parameters, ports, and other pre-instantiation attributes. Hierarchy cannot be modified.
@ TREE_BUILDING
Setting up tree hierarchy only (initial state)
Information describing the type of validation being done.
Definition Resource.hpp:31
PhasedObject which can hold 0 or 1 Resource pointers to an associatedresource. Contains logic for set...
const T getResourceAs() const
Gets the resource contained by this node (if any) as the given type.
virtual std::string getResourceTypeRaw() const
Gets the typename of the resource that this node will eventually contain.
A class that lets you schedule events now and in the future.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Static-initialization order controller.
static StringManager & getStringManager()
Returns the StringManager singleton.
const std::string *const EMPTY
Holds interned empty strings.
std::string * internString(const std::string &s)
Stores a string in shared space within this manager unless it is already stored.
Base class used to extend TreeNode parameter sets.
Temporary delegate for notificaiton invokation until the implementation is working....
delegate & operator=(const delegate &d)
void operator()(const TreeNode &origin, const DataT &data) const
Invokes the delegate.
bool operator==(const delegate &d) const
Compares all fields in this delegate against another delegate.
bool observes(const TreeNode &obs_pt, const std::string *name) const
Compares against another delegate based on the observation point and name ignoring delegate callback ...
static delegate from_method(T *obj, const TreeNode &obs_pt, const std::string &name)
Creates delegate with given properties.
constexpr bool equals(T *obj, const TreeNode &obs_pt, const std::string &name) const
Compares against another delegate's information based on DataT, T, TMethod, observer pointer,...
Container for std::type_info.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
app::Simulation * getSimulation() const
Gets the simulation (if any) associated with this tree.
virtual void broadcastRegistrationForNotificationToChildren_(const std::type_info &tinfo, const std::vector< const std::string * > &name_ids, TreeNode *obs_node, const delegate *del, const bool allow_private)
Recursively notifies children that the notification described is now (or still is) being observed at ...
static const uint32_t RENDER_SUBTREE_INDENT
Spaces to indent for each tree level in sparta::TreeNode::renderSubtree.
Definition TreeNode.hpp:362
void addExtensionParameters(const std::string &extension_name, std::unique_ptr< ParameterSet > extension_params)
Add a named parameter set to extend this tree node's metadata.
static constexpr char NODE_NAME_VIRTUAL_GLOBAL[]
Node name for the virtual glopbal node.
Definition TreeNode.hpp:329
uint32_t findImmediateChildren_(std::regex &expr, std::vector< TreeNode * > &found, bool allow_private=false)
Variant of findImmediateChildren_ with no replacements vector.
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
Definition TreeNode.hpp:303
node_uid_type getNodeUID() const
Gets the unique ID of this node.
bool hasObserversRegisteredForNotification(const std::type_info &tinfo, const std::string *name) const noexcept
Determines if this TreeNode (not descendants) has any observers for this type of event and name.
ConstT getAs() const
Retrieves this node after casting to type T.
const std::vector< const std::string * > & getTags() const
Gets the set of tags associated with this TreeNode.
std::string getLocation() const override final
bool canGenerateNotification(const std::type_info &tinfo, const std::string &name) const
Can this TreeNode generate a notification of the given type having the given name (does not require i...
static std::string getNextName(const std::string &name, size_t &pos)
Gets the next name between two '.' chars in a string starting at pos.
static const node_uid_type MAX_NODE_UID
Maximum value of node_uid_ before the framework throws an exception.
Definition TreeNode.hpp:309
void validateTree_()
Iterates the finalized tree and validates each node (e.g. ensures statistics can be evaluated)
virtual uint32_t findImmediateChildren_(std::regex &expr, std::vector< const TreeNode * > &found, std::vector< std::vector< std::string > > &replacements, bool allow_private=false) const
Const-qualified variant of findImmediateChildren_.
void detachFromChildren_()
Removes a node from its children with the expectation this node will be immediately destroyed (i....
static const std::string DEBUG_DUMP_SECTION_DIVIDER
String dividing sections in a debug dump file.
Definition TreeNode.hpp:324
uint32_t getGroup(const std::string &group, std::vector< TreeNode * > &results)
Gets all nodes in a child group.
void dumpPossibleNotifications(std::ostream &o) const noexcept
Dumps a listing of the notifications which this node can generate to the ostream o.
static constexpr char NODE_NAME_NONE[]
Node name for anonymous node.
Definition TreeNode.hpp:319
static bool hasWildcardCharacters(const std::string &name)
Determines if a given node name has any wildcard characters which will be substituted in createSearch...
static constexpr char GROUP_NAME_BUILTIN[]
Reserved name for built-in nodes.
Definition TreeNode.hpp:370
const std::string & getDesc() const
Gets the description of this node.
TreeNode(TreeNode *parent, const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc, bool is_indexable)
TreeNode full constructor. Initializes node and adds it as a child of an existing tree node (if paren...
virtual TreeNode * getRoot()
Gets farthest ancestor of this node.
size_t getNumExtensions() const
Get the number of extensions for this node.
void markHidden(bool hidden=true)
Marks this TreeNode hidden for the purposes of printint out nodes. This does not make the node inacce...
TreeNode(TreeNode *parent, const std::string &name, const std::string &desc)
TreeNode constructor with no group information.
uint32_t findChildren(const std::string &pattern, std::vector< TreeNode * > &results)
Version of findChildren with no replacements vector.
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
void simulationTerminating_()
Hook to allow simulation resources to clean-up before simulation is ended.
static bool notificationCategoryMatch(const std::string *query_id, const std::string *node_id)
Checks if two notification categories match where one is an actual category.
void dumpPossibleSubtreeNotifications(std::ostream &o) const noexcept
Dumps a listing of the notifications which this node and its descendants can generate to the ostream ...
bool isIndexableByGroup() const
Returns whether this object is accessible through its parent's interfaces for getting children by gro...
const T getParentAs(bool must_exist=true) const
Retrieves a parent casted to type T* if this node has a parent.
Definition TreeNode.hpp:990
void enterTeardown_() noexcept
Recursively enter TREE_TEARDOWN phase while alerting nodes through onEnteringTeardown_ and alterting ...
virtual void addLink(TreeNode *node, const std::string &label)
Link this tree node with another tree node.
bool canSubtreeGenerateNotifications(const std::type_info &tinfo, const std::vector< const std::string * > &names) const
Checks to see if any a subtree can generate any of several notification names which may be patterns.
const std::set< std::string > & getAllExtensionNames()
Extension names, if any. Tree node extensions are typically instantiated on-demand for best performan...
uint32_t findChildrenByTag(const std::string &tag, std::vector< TreeNode * > &results, int32_t max_depth=-1)
Finds a set of all children having the selected tag which this node or descendants of this node withi...
static const uint32_t TEARDOWN_ERROR_LIMIT
Number of teardown-phase-related messages that can be printed before the rest will be suppressed.
Definition TreeNode.hpp:406
void addExtensionFactory(const std::string &extension_name, std::function< ExtensionsBase *()> factory)
Add an extension factory to this tree node by its type (name). This method does not actually create a...
static constexpr char LOCATION_NODE_SEPARATOR_EXPECTING
Separator character between node identifiers in a location string when the child is being attached to...
Definition TreeNode.hpp:346
static std::vector< const std::string * > parseNotificationNameString(const std::string &csl)
Parses a comma-separated list of notification names (or patterns) separated by commas and ignoring wh...
TreeNode * getChildAt(uint32_t idx) const
Gets a child at a position in the children vector in the order in which they were added to this node.
void addAlias(const std::string &alias)
Add a single alias for this node.
uint32_t getPossibleSubtreeNotifications(std::vector< NotificationInfo > &infos) const noexcept
Gets information on the possible notifications generated by this node and all its descendants.
std::shared_ptr< TreeNode > SharedPtr
Shared pointer to TreeNode. Acquire with WeakPtr::lock().
Definition TreeNode.hpp:276
TreeNode(const TreeNode &)=delete
Not copy-constructable.
const TreeNode * getExpectedRoot() const
build-time equivalent to getRoot before an object is actually attached to a tree. This is a mainly a ...
void addChild(TreeNode &child)
AddChild by reference for convenience.
void broadcastDeregistrationForNotificationListStringToChildren_(const std::type_info &tinfo, const std::string &name, TreeNode *obs_node, const delegate *del, const bool private_only)
Symmetric oppostie of broadcastRegistrationForNotificationListStringToChildren_.
void broadcastRegistrationForNotificationListStringToChildren_(const std::type_info &tinfo, const std::string &name, TreeNode *obs_node, const delegate *del, const bool private_only)
Entry point to broadcastRegistrationForNotificationToChildren_ recursion. Breaks a name string.
virtual bool isAttached() const
Is this node part of a device tree with a proper RootTreeNode at the root.
Definition TreeNode.hpp:957
bool canSubtreeGenerateNotification(const std::type_info &tinfo, const std::string &name) const
Can this TreeNode or its descendants (of any distance) generate a notification of the given type havi...
bool isBuiltin() const
Is this node in the builtins group.
static const std::vector< std::pair< const char *, std::function< void(std::string &)> > > TREE_NODE_PATTERN_SUBS
List of pattern susbtitutions when creating a search pattern from a TreeNode name containing wildcard...
Definition TreeNode.hpp:412
void registerForNotification(T *obj, const std::string &name, bool ensure_possible=true)
Registers a callback method to listen for all notifications having the specified data type DataT and ...
void invokeDelegatesOn_(TreeNode *to_invoke, const DataT &data, const std::string *name_id)
Protected wrapper for invokeDelegates_ which allows a TreeNode to invoke delegates on another TreeNod...
TreeNode()=delete
Not default-constructable.
const ChildrenVector getChildren() const
Gets a vector of all children of this node in any group in the order in which they were added to this...
std::string renderSubtree(int32_t max_depth=-1, bool show_builtins=false, bool names_only=false, bool hide_hidden=false, bool(*leaf_filt_fxn)(const TreeNode *)=nullptr) const
Renders the subtree starting at this node as a string containing an indentation-based depth-first rep...
group_idx_type getGroupIndexMax(const std::string &group)
Gets the largest index of a node in the given group.
void verifyUniqueChildIdentifier_(const std::string &ident, bool ignore_group_collision=false)
Verifies that the given identifier is unique for all children of this node by comparing against names...
const std::string * getGroupNamePtr() const
Gets the group name string pointer (interned in StringManager singleton) of this node.
void detachFromParent_()
Removes a node from its parent with the expectation this node will be immediately destroyed (i....
const TreeNode * getChild(const std::string &name, bool must_exist=true) const
Overloaded const-qualified.
TreeNode(TreeNode &&rhp)
Move constructor.
uint32_t getLevel() const
Gets the level of this node. 0 is root.
uint32_t getChildren(std::vector< TreeNode * > &results, bool ignore_builtin_group=true, bool ignore_anonymous_nodes=true)
Gets all children of this node in the order in which they were added to this node.
sparta::TreeNode * findAncestorByName(const std::string &name)
Find ancestor by name.
void validatePostRun_(const PostRunValidationInfo &info) const
Hook to check the state of the simulator post-run and throw exceptions if something is incorrect.
bool isScopeRoot() const
void validateGroup(const std::string &name, const std::string &group, group_idx_type idx)
Validates the given group name string and group index for this TreeNode. Does not consider context (e...
static constexpr char LOCATION_NODE_SEPARATOR_ATTACHED
Separator character between node identifiers in a location string when the child is attached to the p...
Definition TreeNode.hpp:337
virtual void broadcastDeregistrationForNotificationToChildren_(const std::type_info &tinfo, const std::vector< const std::string * > &name_ids, TreeNode *obs_node, const delegate *del, const bool allow_private)
Recursively notifies children that the notification described has lost one particular observer (del) ...
DelegateVector::iterator findDelegate_(DelegateVector &dvec, T *obj, const std::string &target_name)
Finds a delegate associated with the given type T, object pointer, DataT, and TMethod within a Deleva...
static const std::map< const TreeNode *, WeakPtr > & getAllNodes()
Gets the vector of all TreeNodes currently known to be constructed.
void enterFinalizing_()
Recursively enter TREE_FINALIZING phase.
bool hasTag(const std::string &tag) const
Does this node have a specific tag (by name)
void validateDesc(const std::string &desc)
Validates the given description string for this TreeNode.
Scheduler * getScheduler(const bool must_exist=false)
Get the scheduler associated with this tree node's root.
const std::string * getNamePtr() const
Gets the name of this node's string pointer which isinterned in StringManager)
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
uint32_t group_idx_type
Index within a group.
Definition TreeNode.hpp:261
TreeNode(TreeNode *parent, const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc)
TreeNode constructor with no is_indexable parameter [defaults to true].
bool areParametersLocked_() const
This method informs whether the tree is past the lockdown phase for all LOCKED and HIDDEN parameters....
const TreeNode * getScopeRoot() const
static bool matchesGlobLike(const std::string &pattern, const std::string &other)
Determine if a glob-like search pattern matches some other string.
static std::string getPreviousName_(const std::string &name, size_t &pos)
Gets the previous name between two '.' chars in a string starting at pos.
void postPropagatingNotification_(const TreeNode *origin, const DataT &data, const std::string *name_id)
Starts a notification propagating up the tree.
void enterFinalized_()
Recursively enter TREE_FINALIZED phase.
static const uint64_t CHILD_GET_THRESHOLD
Threshold for number of getChild calls after finalization before a warning message is printed about f...
Definition TreeNode.hpp:400
const Clock * getLocalClock()
Gets the clock associated directly with this Node. This is useful for configuration and simulator deb...
const AliasVector & getAliases() const
Gets a vector of all aliases of this node.
bool hasTag(const std::string *interned_tag_name) const
Does this node have a specific tag (by string pointer interned with StringManager)....
ExtensionsBase * getExtension()
Get an extension without needing to specify any particular type string. If no extensions exist,...
std::string getDeepestMatchingPath(const std::string &path) const
Gets the deepest whole node location starting from this node that matches some part of path starting ...
void deregisterForNotification(T *obj, const std::string &name)
Removes at most one registration made with registerForNotification.
std::multimap< std::string, TreeNode * > ChildNameMapping
Mapping of names, aliases, and groups to individual child nodes within one node. This must be in a de...
Definition TreeNode.hpp:256
bool canGenerateNotification(const std::type_info &tinfo, const std::string *name) const
Can this TreeNode generate a notification of the given type having the given name or pattern.
std::weak_ptr< TreeNode > WeakPtr
Weak pointer to a TreeNode. Acquire with getWeakPtr.
Definition TreeNode.hpp:266
virtual void activateLink(const std::string &label)
Activate one of the links added with addLink.
TreeNode(TreeNode *parent, const std::string &group, group_idx_type group_idx, const std::string &desc)
TreeNode constructor for anonymous node with group information.
std::vector< std::string > AliasVector
Vector of aliases (other names for this node)
Definition TreeNode.hpp:248
void finalizeTree_()
Recursively create resources based on tree configuration. enter_finalize_ should be invoked after thi...
virtual uint32_t findImmediateChildren_(std::regex &expr, std::vector< TreeNode * > &found, std::vector< std::vector< std::string > > &replacements, bool allow_private=false)
Finds immediate children with some identity (name or alias) matching a regex.
WeakPtr getWeakPtr()
Gets a weak pointer to this TreeNode. This weak pointer is guaranteed to expire when this TreeNode is...
static constexpr char LOCATION_NODE_SEPARATOR_UNATTACHED
Separator character preceding a node identifiers in a location string when that node has no parent an...
Definition TreeNode.hpp:355
TreeNode(const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc)
TreeNode constructor with no parent Node.
static TreeNode * getVirtualGlobalNode()
Gets the virtual global node singleton. This node can have no parent and no children....
virtual void setClock(const Clock *clk)
Assigns a clock to this node. This clock will then be accessed by any descendant which has no assigne...
std::string getDisplayLocation() const
Returns the location of this node in the device tree which might not be usable for navigating the dev...
std::pair< uint32_t, std::string > recursGetDeepestMatchingPath_(const std::string &path, size_t name_pos) const
Finds the deepest node path mathing the input path. Implements getDeepestMatchingPath.
uint32_t locateNotificationSources(std::vector< TreeNode * > &nodes, const std::string &name="")
Gets all possible notification info from NotificationSources within this node's subtree.
void getDelegatesRegisteredForNotification(const std::type_info &tinfo, const std::string *name, std::vector< delegate > &dels) noexcept
Gets the vector of delegates registered for a notification on this TreeNode.
std::vector< const std::string * > getIdentifiers() const
Gets all the identifiers for this node (excluding groups)
bool isExpired() const
Is this expired (i.e. has it been the rhp of a move constructor)
virtual TreeNode * getParent()
Gets immediate parent of this node if one exists.
Definition TreeNode.hpp:965
bool isDescendantOf(const TreeNode *ancestor, int32_t max_depth=-1) const
Determines if this node is a descendant of the specified ancestor node within some number of generati...
void dumpDebugContent_(std::ostream &out) const noexcept
Allows resources to write out detailed textual debugging information about the node....
void lockdownParameters()
Method to put the device tree in lockdown phase. All LOCKED and HIDDEN parameters are frozen after th...
Definition TreeNode.hpp:430
static std::string createSearchRegexPattern(const std::string &pat)
Compute a regex pattern for a node child path containing any number of wildcard characters (not a dot...
group_idx_type getGroupIdx() const
Gets the group index of this node.
ExtensionsBase * getExtension(const std::string &extension_name)
Get an extension object by type string. Returns nullptr if not found (unrecognized).
uint32_t getRecursiveNodeCount() const
Recursively gets the count of a nodes that are a subclass of a particular type (determined by dynamic...
const ConstT getChildAs(const std::string &name, bool must_exist=true) const
Retrieves a child that is castable to T with the given dotted path.
static bool identityMatchesPattern_(const std::string &ident, std::regex &expr, std::vector< std::string > &replacements)
Performs pattern matching on a identity string.
virtual std::string stringize(bool pretty=false) const
Create a string representation of this node.
Definition TreeNode.hpp:723
const T * getAs() const
Retrieves this node after casting to type const T.
std::vector< delegate > DelegateVector
Vector of delegates representing a list of observers to notify.
std::map< const std::string *, std::vector< TreeNode * > > TagsMap
Map of strings (interned in StringManager) tags to TreeNodes.
Definition TreeNode.hpp:281
std::map< type_info_container, DelegateVector > NotificationObserverMap
Map of delegate vectors containing all observers.
void stringizeTags(std::stringstream &ss) const
Render tags to a string in the form: " tags:[tag0, tag1]" If there are any tags. The leading space ma...
Definition TreeNode.hpp:743
const std::string & getName() const override
Gets the name of this node.
void enterConfig_() noexcept
Recursively enter TREE_CONFIGURING phase.
sparta::TreeNode * findAncestorByTag(const std::string &tag)
Find the first ancestor with a particular tag.
uint32_t getNumChildren() const
Gets the number of children that this node has including those in the sparta builtins group.
TreeNode * getChild(const std::string &name, bool must_exist=true)
Retrieves a child with this dotted path name.
void addTags(const std::vector< std::string > &v)
Adds each elements of a vector of tags to this node.
uint32_t getGroupSize(const std::string &group)
Gets the number of nodes in a group.
bool canGenerateNotification(const NotificationInfo &info) const
Can this TreeNode generate a notification of the given NotificationInfo.
uint32_t getChildrenOfType(std::vector< T * > &results) const
return all the children matching a particular type using dynamic cast.
void validateName(const std::string &nm)
Validates the given name string for this TreeNode. Does not consider context (e.g....
bool isHidden() const
Is this TreeNode supposed to be hidden during tree printouts This value does not have to be respected...
std::string getExpectedLocation() const
build-time equivalent to getLocation before an object is actually attached to a tree....
T getAs()
Retrieves this node after casting to type const T.
static std::string formatAllNodes()
Prints the list of all TreeNodes currently known to be constructed.
TreeNode * getScopeRoot()
void removeChildForTeardown_(TreeNode *child)
"Removes" the given child by invoking onDestroyingChild_ then removing this child from the children_ ...
bool hasImmediateChild(const TreeNode *n) const noexcept
Determines if the node n is an immediate child of this node.
void addAliases(const AliasVector &v)
Adds each element of a vector of aliases to this node..
static const uint64_t CHILD_FIND_THRESHOLD
Threshold for number of findChildren calls after finalization before a warning message is printed abo...
Definition TreeNode.hpp:392
void addTag(const std::string &tag)
Adds single tag to this node.
TreeNode(const std::string &name, const std::string &desc)
TreeNode constructor with no parent node or group information.
bool canSubtreeGenerateNotification(const std::type_info &tinfo, const std::string *name) const
Can this TreeNode or its descendants (of any distance) generate a notification of the given type havi...
void bindTreeLate_()
Recursively invoke TreeNode::onBindTreeEarly_ and Resource::onBindTreeLate_ (in that order for each n...
uint32_t getChildrenIdentifiers(std::vector< std::string > &idents, bool ignore_builtin_group=true) const
Gets all child identifiers, aliases, group names, and group-aliases which can be used to refer to a c...
static bool isNodeConstructed(const TreeNode *)
Is a given node constructed?
virtual ~TreeNode()
Virtual destructor.
uint32_t findChildren(const std::string &pattern, std::vector< TreeNode * > &results, std::vector< std::vector< std::string > > &replacements)
Finds all children starting at this node with a given pattern relative to this node by matching names...
sparta::TreeNode * findAncestorByType()
Find ancestor by type.
T * getAs()
Retrieves this node after casting to type const T.
TreeNode & operator=(const TreeNode &)=delete
Not assign-constructable.
const std::string & getGroup() const
Gets the group name of this node.
bool isAnonymous() const
Is this node anonymous.
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
void bindTreeEarly_()
Recursively invoke TreeNode::onBindTreeEarly_ and Resource::onBindTreeEarly_ (in that order for each ...
T * findAncestorResourceByType()
Find an ancestor's resource with a certain type.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
uint32_t findImmediateChildren_(std::regex &expr, std::vector< const TreeNode * > &found, bool allow_private=false) const
Variant of const-qualified findImmediateChildren_ with no replacements vector.
void makeSubtreePrivate()
Make the entire subtree private.
std::vector< TreeNode * > ChildrenVector
Vector of TreeNode children.
Definition TreeNode.hpp:243
uint32_t getPossibleNotifications(std::vector< NotificationInfo > &infos) const
Gets information on the possible notifications generated by this node (excludes children).
ConstWeakPtr getWeakPtr() const
Const variant of getWeakPtr.
uint64_t node_uid_type
Type of unique-identifier assigned to every node.
Definition TreeNode.hpp:238
void removeFromParentForTeardown_(TreeNode *parent)
Protected Wrapper for getParent()->removeChildForTeardown_ which allows subclases of TreeNode to indi...
bool locationMatchesPattern(const std::string &pattern, const TreeNode *pat_loc) const
Determines if the given pattern (which may contain wildcards) can describe this node.
void dumpLocatedNotificationSources(std::ostream &o, const std::string &name="")
Retrieves the relevant NotificationSources from locateNotificationSources and prints them to the outp...
std::weak_ptr< const TreeNode > ConstWeakPtr
Weak pointer to a const TreeNode. Acquire with getWeakPtr.
Definition TreeNode.hpp:271
static bool identityMatchesPattern_(const std::string &ident, std::regex &expr)
Variant of identityMatchesPattern_ with no replacements vector.
bool hasChild(const std::string &name) const noexcept
Determines if a child can be found with the given dotted path.
Virtual global node for all device trees in a single simulation. This node acts a potential notificat...
Simulator which builds a sparta DeviceTree.
Macros for handling exponential backoff.
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo
std::string demangle(const std::string &name) noexcept
Demangles a C++ symbol.
Definition Utils.hpp:214
Type for indicating that ANY notification source type should be included in a search performed by loc...
Definition TreeNode.hpp:290
Notification type/name information.
const TreeNode * origin
TreeNode from which this notification can be generated.
NotificationInfo(const NotificationInfo &rhp)
Copy constructor.
void checkValid() const
Ensures the node contains valid data.
NotificationInfo(const NotificationInfo &&rhp)
Move constructor.
const std::string * name
String interned by StringManager. Must not be nullptr.
NotificationInfo & operator=(const NotificationInfo &rhp)
Assignment operator.
const std::type_info * tinfo
Type from typeid() on notification DataT.
NotificationInfo(const TreeNode *_origin, const std::type_info *_tinfo, const std::string *_name)
Basic constructor.