The Sparta Modeling Framework
Loading...
Searching...
No Matches
NotificationSource.hpp
1// <NotificationSource> -*- C++ -*-
2
3#pragma once
4
5#include <iostream>
6#include <vector>
7
11#include "sparta/utils/StringManager.hpp"
12namespace sparta
13{
14
56 #define REGISTER_FOR_THIS(func) \
57 registerForThis<typename std::remove_reference<decltype(*this)>::type, \
58 &std::remove_reference<decltype(*this)>::type::func>(this);
59
65 #define DEREGISTER_FOR_THIS(func) \
66 deregisterForThis<typename std::remove_reference<decltype(*this)>::type, \
67 &std::remove_reference<decltype(*this)>::type::func>(this);
68
69 template<typename T>
70 class MirrorNotificationSource;
71
79 {
80 public:
86 template <typename T>
90
94
105
112 typedef std::function<void (NotificationSourceBase const &, uint32_t)> callback_t;
113
161
163 callback_t callback_;
164 TreeNode::ConstWeakPtr tree_node_weak_ptr_;
166
167 public:
168
171 callback_t callback)
172 : type_(type),
173 callback_(callback),
174 tree_node_weak_ptr_(ns.getWeakPtr()),
175 ns_(ns)
176 {
177 ObservationStateCallbackPrivateInterface::registerObservationStateChangeCallback_(ns_, this);
178 }
179
181 {
182 // Deregister from notification ONLY if the node has not been destroyed already
183 if (tree_node_weak_ptr_.expired() == false) {
184 ObservationStateCallbackPrivateInterface::deregisterObservationStateChangeCallback_(ns_, this);
185 }
186 }
187
190 ObservationStateCallback& operator= (const ObservationStateCallback&) = delete;
191
195 ObservationStateChange getType() const { return type_; }
196
201 uint32_t observers) const
202 {
203 callback_(ns, observers);
204 }
205
209 void dump(std::ostream& o) const {
210 o << "<ObservationStateCallback type=" << static_cast<int>(type_) << " node=";
211 if(tree_node_weak_ptr_.expired()){
212 o << "EXPIRED";
213 }else{
214 o << tree_node_weak_ptr_.lock()->getLocation();
215 }
216 o << ">";
217 }
218 };
219
225 private:
226 static void registerObservationStateChangeCallback_(NotificationSourceBase & ns,
227 ObservationStateCallback* const cbobject)
228 {
229 ns.registerObservationStateChangeCallback_(cbobject);
230 }
231
232
233 static void deregisterObservationStateChangeCallback_(NotificationSourceBase & ns,
234 ObservationStateCallback* const cbobject)
235 {
236 ns.deregisterObservationStateChangeCallback_(cbobject);
237 }
238
240 };
241
243
246
250
270 const std::string& name,
271 const std::string& group,
272 TreeNode::group_idx_type group_idx,
273 const std::string& desc,
274 const std::string* notification_name_id,
275 const std::type_info& notification_tinfo) :
276 TreeNode(name, group, group_idx, desc),
277 noti_id_(notification_name_id),
278 noti_tinfo_(notification_tinfo),
279 observed_(false),
280 num_posts_(0)
281 {
282 if(nullptr == parent){
283 throw SpartaException("NotificationSourceBase ")
284 << getLocation() << " must be constructed with a parent";
285 }
286
287 setExpectedParent_(parent);
288
289 if(nullptr == notification_name_id){
290 throw SpartaException("NotificationSourceBase ")
291 << getLocation() << " cannot be constructed with a null notification_name_id";
292 }
293
294 // Other initialization here
295 // ...
296
297 validateNotificationName(*notification_name_id);
298
299 parent->addChild(this);
300
301 determineObs_Nodes_();
302 }
303
309 const std::string& name,
310 const std::string& group,
311 TreeNode::group_idx_type group_idx,
312 const std::string& desc,
313 const std::string& notification_name,
314 const std::type_info& notification_tinfo) :
315 NotificationSourceBase(parent, name, group, group_idx, desc,
316 StringManager::getStringManager().internString(notification_name),
317 notification_tinfo)
318 { }
319
320
325
330 bool observed() const noexcept {
331 return observed_;
332 }
333
344 static void validateNotificationName(const std::string& nm)
345 {
346 for(const char* rsrv : RESERVED_WORDS){
347 if(nm == rsrv){
348 throw SpartaException("Notification name \"")
349 << nm << "\" is a reserved word. ";
350 }
351 }
352
353 if(nm.size() > 0 && nm[0] == '_'){
354 throw SpartaException(" Notification name \"")
355 << nm << "\" begins with an '_' which is not permitted";
356 }
357
358 if(nm.find("__") != std::string::npos){
359 throw SpartaException(" Notification name \"")
360 << nm << "\" contains two adjacent underscores which is not permitted";
361 }
362
363 if(nm.find_first_of(DIGIT_CHARS) == 0){
364 throw SpartaException(" Notification name \"")
365 << nm << "\" begins with a '" << nm[nm.size()-1] << "' character which is not permitted. "
366 << "A Notification name must not begin with a decimal digit.";
367 }
368
369 size_t pos = nm.find_first_not_of(ALPHANUM_CHARS);
370 if(pos != std::string::npos){
371 throw SpartaException("Notification name \"")
372 << nm << "\" contains a '" << nm[pos] << "', which is not permitted. "
373 << "A Notification name must contain only alphanumeric characters and underscores.";
374 }
375 }
376
379
383
390 const std::string* getNotificationID() const {
391 return noti_id_;
392 }
393
398 const std::string& getNotificationName() const {
399 return *noti_id_;
400 }
401
406 const std::type_info& getNotificationType() const {
407 return noti_tinfo_;
408 }
409
415 const std::string getNotificationTypeName() const {
416 return demangle(noti_tinfo_.name());
417 }
418
421
431 const std::vector<TreeNode*>& getObservationPoints() const {
432 return obs_nodes_;
433 }
434
444 uint32_t getNumObservationPoints() const {
445 return obs_nodes_.size();
446 }
447
453 uint32_t getNumObservers() const {
454 return dels_.size();
455 }
456
460 uint64_t getNumPosts() const {
461 return num_posts_;
462 }
463
464 protected:
465
466 const std::string* noti_id_;
467 const std::type_info& noti_tinfo_;
468
473 std::vector<TreeNode*> obs_nodes_;
474
483 std::vector<delegate> dels_;
484
486
491 mutable uint64_t num_posts_;
492
493 // Override from TreeNode
495 virtual void notificationObserverAdded_(const std::type_info& tinfo,
496 const std::string* name_id,
497 TreeNode* obs_node,
498 const delegate* del) override {
499 // Expected to only see observation on the notification that this source can
500 // generate. If these assertions are hit, then the framework is broken or
501 // canGenerateNotification_ is incorrect
502 sparta_assert(tinfo == noti_tinfo_);
503 sparta_assert(name_id == noti_id_ || name_id == StringManager::getStringManager().EMPTY);
504
505 // Add the observation point node if unique
506 auto itr = std::find(obs_nodes_.begin(), obs_nodes_.end(), obs_node);
507 if(itr == obs_nodes_.end()){
508 obs_nodes_.push_back(obs_node);
509 }
510
511 dels_.push_back(*del);
512
513 const bool was_observed = observed_;
514 observed_ = true;
515
516 // Callback happen after state changes are complete (or before) in order to allow recursion
517 if(not was_observed){
518 invokeObservationStateChangeCallbacks_(ObservationStateChange::SOLE_OBSERVER_REGISTERING);
519 }
520 invokeObservationStateChangeCallbacks_(ObservationStateChange::OBSERVER_REGISTERING);
521 }
522
523 // Override from TreeNode
525 virtual void notificationObserverRemoved_(const std::type_info& tinfo,
526 const std::string* name_id,
527 TreeNode* obs_node,
528 const delegate* del) override {
529 // Expected to only see observation on the notification that this source can
530 // generate. If these assertions are hit, then the framework is broken or
531 // canGenerateNotification_ is incorrect
532 sparta_assert(tinfo == noti_tinfo_);
533 sparta_assert(name_id == noti_id_ || name_id == StringManager::getStringManager().EMPTY);
534
535 const bool was_observed = observed_;
536
537 auto delitr = std::find(dels_.begin(), dels_.end(), *del);
538 if(delitr != dels_.end()){
539 dels_.erase(delitr);
540 }
541
542 observed_ = dels_.size() > 0;
543
544 // Remove the observation point node if no delegates refer to it any more
545 bool remaining = false;
546 for(auto d : dels_){
547 if(d.getObservationPoint() == obs_node){
548 remaining = true;
549 break;
550 }
551 }
552 if(false == remaining){
553 auto itr = std::find(obs_nodes_.begin(), obs_nodes_.end(), obs_node);
554 if(itr != obs_nodes_.end()){
555 obs_nodes_.erase(itr);
556 }
557 }
558
559 // Callback happen after state changes are complete (or before) in order to allow recursion
560 // Reverse order of callback from notificationObserverAdded_.
561 invokeObservationStateChangeCallbacks_(ObservationStateChange::OBSERVER_DEREGISTERING);
562 if(was_observed && not observed_){
563 invokeObservationStateChangeCallbacks_(ObservationStateChange::SOLE_OBSERVER_DEREGISTERING);
564 }
565 }
566
567 // Override from TreeNode
568 // Returns true only for matches on node's notification ID or the input pattern
569 bool canGenerateNotification_(const std::type_info& tinfo,
570 const std::string* id,
571 const std::string*& match) const override {
572 if(noti_tinfo_ != tinfo && tinfo != typeid(sparta::TreeNode::ANY_TYPE)){
573 return false;
574 }
575
577 match = noti_id_;
578 return true;
579 }
580
581 return false;
582 }
583
584 // Override from TreeNode
585 virtual std::string stringize(bool pretty=false) const override {
586 (void) pretty;
587 std::stringstream ss;
588 ss << '<' << getLocation() << " name:\""
589 << getNotificationName() << "\" datat:(" << getNotificationTypeName()
590 << ") " << " observers:" << getNumObservers()
591 << " posted:" << getNumPosts() << '>';
592 return ss.str();
593 }
594 private:
595
596 // Override from TreeNode
597 virtual void onAddedAsChild_() noexcept override final {
598 determineObs_Nodes_();
599 }
600
601
611 void determineObs_Nodes_() {
612 obs_nodes_.clear();
613 dels_.clear();
614 observed_ = false;
615
616 TreeNode* node = this;
617 while(node){
618 node->getDelegatesRegisteredForNotification(noti_tinfo_, noti_id_, dels_);
619 if(node->hasObserversRegisteredForNotification(noti_tinfo_, noti_id_)){
620 obs_nodes_.push_back(node);
621 }
622 node = node->getParent();
623 }
624
625 node = getVirtualGlobalNode();
626 node->getDelegatesRegisteredForNotification(noti_tinfo_, noti_id_, dels_);
627 if(node->hasObserversRegisteredForNotification(noti_tinfo_, noti_id_)){
628 obs_nodes_.push_back(node);
629 }
630
631 // Update observed flag
632 observed_ = dels_.size() > 0;
633 }
634
635 // Override from TreeNode
636 // Adds this node's notification info
637 void getPossibleNotifications_(std::vector<NotificationInfo>& infos) const override {
638 infos.emplace_back(this, &noti_tinfo_, noti_id_);
639 }
640
644 void registerObservationStateChangeCallback_(ObservationStateCallback* const hook) {
645 // User errors
646 sparta_assert(in_observation_state_change_callback_ == false,
647 "cannot add observation state change callbacks from within a callback");
648
649 // Internal errors
650 sparta_assert(hook); // Internal-only hook argument is null somehow?
651 sparta_assert(std::find(obs_state_change_cbs_.begin(), obs_state_change_cbs_.end(), hook) == obs_state_change_cbs_.end(),
652 "Internal notification hook " << *hook
653 << " was installed a second time to notification source " << *this);
654
655 // Track it in a list
656 obs_state_change_cbs_.emplace_back(hook);
657 }
658
662 void deregisterObservationStateChangeCallback_(ObservationStateCallback* const hook) {
663 // User errors
664 sparta_assert(in_observation_state_change_callback_ == false,
665 "cannot remove observation state change callbacks from within a callback");
666
667 const auto itr = std::find(obs_state_change_cbs_.begin(), obs_state_change_cbs_.end(), hook);
668
669 // Internal error checking
670 sparta_assert(itr != obs_state_change_cbs_.end(),
671 "Internal notification hook " << *hook
672 << " was not found while attemptint to deregister it from notification source " << *this);
673
674 // Remove it so it is no longer called
675 obs_state_change_cbs_.erase(itr);
676 }
677
683 void invokeObservationStateChangeCallbacks_(ObservationStateChange to_call) {
684 // User Error
685 sparta_assert(in_observation_state_change_callback_ == false,
686 "cannot recursively invoke observation state change callbacks from within a "
687 "callback. User may be changing Notification Observers in response to "
688 "changes in observation state. This is not allowed");
689
690 in_observation_state_change_callback_ = true;
691
692 // Break on first exception!
693 try {
694 for(ObservationStateCallback const * cb : obs_state_change_cbs_){
695 if(cb->getType() == to_call){
696 (*cb)(*this, getNumObservers());
697 }
698 }
699 } catch (...) {
700 in_observation_state_change_callback_ = false;
701
702 throw; // Re-throw
703 }
704
705 in_observation_state_change_callback_ = false;
706 }
707
716 std::vector<ObservationStateCallback*> obs_state_change_cbs_;
717
726 bool in_observation_state_change_callback_ = false;
727 };
728
729
738 template <typename NotificationDataT>
740 {
741 public:
742
743 typedef NotificationDataT data_type;
744 typedef NotificationDataT const const_data_type;
745
749
763 const std::string& name,
764 const std::string& group,
765 TreeNode::group_idx_type group_idx,
766 const std::string& desc,
767 const std::string* notification_name_id) :
768 NotificationSourceBase(parent, name, group, group_idx,
769 desc, notification_name_id,
770 typeid(NotificationDataT))
771 {
772 static_assert(std::is_same<
773 typename std::remove_cv<
774 typename std::remove_reference<
775 typename std::remove_pointer<NotificationDataT>::type
776 >::type
777 >::type,
778 NotificationDataT
779 >::value,
780 "NotificationDataT must NOT be a const, volatile, pointer, or reference"
781 "type. It violates at least one of these restrictions");
782
783 // Other initialization here
784 // ...
785 }
786
787 // Alternate constructor
789 const std::string& name,
790 const std::string& group,
791 TreeNode::group_idx_type group_idx,
792 const std::string& desc,
793 const std::string& notification_name) :
794 NotificationSource(parent,
795 name,
796 group,
797 group_idx,
798 desc,
799 StringManager::getStringManager().internString(notification_name))
800 {
801 // Initialization handled in constructor delegation
802 }
803
804 // Alternate constructor
805 NotificationSource(TreeNode* parent,
806 const std::string& name,
807 const std::string& desc,
808 const std::string* notification_name_id) :
809 NotificationSource(parent,
810 name,
811 TreeNode::GROUP_NAME_NONE,
812 TreeNode::GROUP_IDX_NONE,
813 desc,
814 notification_name_id)
815 {
816 // Initialization handled in constructor delegation
817 }
818
819 // Alternate constructor
820 NotificationSource(TreeNode* parent,
821 const std::string& name,
822 const std::string& desc,
823 const std::string& notification_name) :
824 NotificationSource(parent,
825 name,
828 desc,
829 StringManager::getStringManager().internString(notification_name))
830 {
831 // Initialization handled in constructor delegation
832 }
833
834 // Alternate constructor with anonymous name
835 NotificationSource(TreeNode* parent,
836 const std::string& group,
837 TreeNode::group_idx_type group_idx,
838 const std::string& desc,
839 const std::string* notification_name_id) :
840 NotificationSource(parent,
841 "",
842 group,
843 group_idx,
844 desc,
845 notification_name_id)
846 {
847 // Initialization handled in constructor delegation
848 }
849
850 // Alternate constructor with anonymous name
851 NotificationSource(TreeNode* parent,
852 const std::string& group,
853 TreeNode::group_idx_type group_idx,
854 const std::string& desc,
855 const std::string& notification_name) :
856 NotificationSource(parent,
857 "",
858 group,
859 group_idx,
860 desc,
861 StringManager::getStringManager().internString(notification_name))
862 {
863 // Initialization handled in constructor delegation
864 }
865
871
872
873
877
920 template <typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const_data_type&)>
921 void registerForThis(T* obj) {
922 sparta::TreeNode::registerForNotification<data_type, T, TMethod>(obj, *noti_id_);
923 }
924
925 // Overload accepting a class member function signature having only a data argument
926 template <typename T, void (T::*TMethod)(const_data_type&)>
927 void registerForThis(T* obj) {
928 sparta::TreeNode::registerForNotification<data_type, T, TMethod>(obj, *noti_id_);
929 }
930
939 template <typename T, void (T::*TMethod)(const TreeNode&, const TreeNode&, const_data_type&)>
940 void deregisterForThis(T* obj) {
941 sparta::TreeNode::deregisterForNotification<data_type, T, TMethod>(obj, *noti_id_);
942 }
943
944 // Overload accepting a class member function signature having only a data argument
945 template <typename T, void (T::*TMethod)(const_data_type&)>
946 void deregisterForThis(T* obj) {
947 sparta::TreeNode::deregisterForNotification<data_type, T, TMethod>(obj, *noti_id_);
948 }
949
954 void postNotification(const NotificationDataT& data) const {
955 ++num_posts_;
956
957 // Could notify observers at this node and above through TreeNode's propagation interface
958 //sparta_assert(getParent() != nullptr,
959 // "Cannot postNotification from NotificationSource " << getLocation() << " because parent is null");
960 //postPropagatingNotification_(this, data, noti_id_);
961
962 // Could Notify all observing TreeNodes and allow them to invoke delegates
963 //for(TreeNode* o_node : obs_nodes_){
964 // invokeDelegatesOn_(o_node, data, noti_id_);
965 //}
966
967 // Directly invoke all applicable delegates.
968 // Note that this works even if ancestors are destroyed because
969 // deregistration does not take place.
970 for(const delegate& d : dels_){
971 d(*this, data);
972 }
973 }
974
977 };
978
987 template<typename NotificationDataT>
989 {
990 typedef std::vector<NotificationSourceBase*> SrcList;
991 public:
1008 const std::string& name,
1009 const std::string& group,
1010 TreeNode::group_idx_type group_idx,
1011 const std::string& desc,
1012 const std::string* notification_name_id):
1013 NotificationSourceBase(parent, name, group, group_idx, desc,
1014 notification_name_id,
1015 typeid(NotificationDataT))
1016 {}
1017
1023 const std::string& name,
1024 const std::string& group,
1025 TreeNode::group_idx_type group_idx,
1026 const std::string& desc,
1027 const std::string& notification_name) :
1028 NotificationSourceBase(parent, name, group, group_idx,
1029 desc,
1030 notification_name,
1031 typeid(NotificationDataT))
1032 {}
1033
1034 // Alternate constructor
1036 const std::string& name,
1037 const std::string& desc,
1038 const std::string& notification_name) :
1040 name,
1043 desc,
1044 StringManager::getStringManager().internString(notification_name))
1045 {}
1046
1058 void addLink(TreeNode *node, const std::string &label) override final
1059 {
1060 (void)label; // We do not care about the label.
1061 sparta_assert(node != nullptr);
1062 const uint32_t prev_size = concretes_.size();
1063 findMatchingSourcesBelowNode_(*node, concretes_);
1064 // Make sure we found atleast 1 node that we are shadowing,
1065 // otherwise this MirrorNotificationSource is not linked to
1066 // anyone and should be taken out.
1067 if (concretes_.size() - prev_size == 0)
1068 {
1069 SpartaException ex("MirrorNotificationSource \"");
1070 ex << getName() << "\" was unable to bind to any real NotificationSources"
1071 << " found under the nodes provided to addLink().";
1072 throw ex;
1073 }
1074 }
1075 private:
1076
1081 void findMatchingSourcesBelowNode_(sparta::TreeNode& node,
1082 SrcList& bases)
1083 {
1084 auto* as_src = dynamic_cast<NotificationSourceBase*>(&node);
1085 if (as_src)
1086 {
1087 // If this MirrorNotificationSource happened to live under the search
1088 // of node, then we would certainly not want to add ourselves as a
1089 // concrete instance!
1090 if (as_src != this)
1091 {
1092 // We won't mirror anything that isn't explicitly allowed by the concrete
1093 // source.
1094 if (as_src->getNotificationID() == getNotificationID() &&
1095 as_src->getNotificationType() == getNotificationType())
1096 {
1097 bases.emplace_back(dynamic_cast<NotificationSourceBase*>(&node));
1098 }
1099 }
1100 }
1101
1102 for (auto n : node.getChildren())
1103 {
1104 findMatchingSourcesBelowNode_(*n, bases);
1105 }
1106
1107 }
1108 // Override from TreeNode
1110 void notificationObserverAdded_(const std::type_info& tinfo,
1111 const std::string* name_id,
1112 TreeNode* obs_node,
1113 const delegate* del) override final
1114 {
1115 if (del->revealsOrigin())
1116 {
1117 SpartaException ex("Cannot register for notification \"");
1118 ex << *name_id << "\"" << " because this notification source "
1119 << "is only shadowing a private concrete notification source. "
1120 << "The callback signature type would reveal access to a private node "
1121 << "and be misleading. We do not support this feature at this time.";
1122 throw ex;
1123 }
1124
1125 if (concretes_.size() == 0)
1126 {
1127 SpartaException ex ("Cannot register for notification \"");
1128 ex << *name_id << "\" because this is a MirrorNotificationSource "
1129 << "that is not linked to any concrete sources. It is possible you "
1130 << "are registering for the notification too early and should be registering "
1131 << "during onBindTreeLate_()";
1132 throw ex;
1133 }
1134 for(auto concrete : concretes_)
1135 {
1136 concrete->notificationObserverAdded_(tinfo, name_id,
1137 obs_node, del);
1138 }
1139 }
1140 // Override from TreeNode
1142 void notificationObserverRemoved_(const std::type_info& tinfo,
1143 const std::string* name_id,
1144 TreeNode* obs_node,
1145 const delegate* del) override final
1146 {
1147 if (concretes_.size() == 0)
1148 {
1149 SpartaException ex ("Cannot deregister for notification \"");
1150 ex << *name_id << "\" because this is a MirrorNotificationSource "
1151 << "that is not linked to any concrete sources. It is possible you "
1152 << "are deregistering for the notification too early and should be registering "
1153 << "during onBindTreeLate_()";
1154 throw ex;
1155 }
1156
1157 for(auto concrete : concretes_)
1158 {
1159 concrete->notificationObserverRemoved_(tinfo, name_id,
1160 obs_node, del);
1161 }
1162 }
1163 // Override from TreeNode
1164 // Returns true only for matches on node's notification ID or the input pattern
1165 bool canGenerateNotification_(const std::type_info& tinfo,
1166 const std::string* id,
1167 const std::string*& match) const override final
1168 {
1169 if (concretes_.size() == 0)
1170 {
1171 return false;
1172 }
1173 bool can_generate = true;
1174 for (auto noti_src : concretes_)
1175 {
1176 can_generate &= noti_src->canGenerateNotification_(tinfo, id, match);
1177 }
1178 return can_generate;
1179 }
1180
1187 void validateNode_() const override final
1188 {
1189 if (concretes_.size() == 0)
1190 {
1191 SpartaException ex("Unbound MirrorNotificationSource ");
1192 ex << getName() << " was never bound to concrete notification sources.";
1193 throw ex;
1194 }
1195 }
1196
1197 // Override from TreeNode
1198 virtual std::string stringize(bool pretty=false) const override final {
1199 (void) pretty;
1200 std::stringstream ss;
1202 ss << " shadows: ";
1203 try{
1204 ss << concretes_.size() << " sources ";
1205 }
1206 catch (SpartaException&)
1207 {
1208 ss << "[UNAVAILABLE]";
1209 }
1210 return ss.str();
1211 }
1213 SrcList concretes_;
1214 };
1215
1216 inline std::ostream& operator<<(std::ostream& o, const NotificationSourceBase::ObservationStateCallback& osc)
1217 {
1218 osc.dump(o);
1219 return o;
1220 }
1221
1222 inline std::ostream& operator<<(std::ostream& o, const NotificationSourceBase::ObservationStateCallback* osc)
1223 {
1224 if(osc == nullptr){
1225 o << "nullptr";
1226 }else{
1227 o << *osc;
1228 }
1229 return o;
1230 }
1231
1232} // namespace sparta
1233
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.
Basic Node framework in sparta device tree composite pattern.
#define RESERVED_WORDS
Reserved words in Python language, Python builtins, and other reservations. TreeNode names and groups...
Definition TreeNode.hpp:68
#define ALPHANUM_CHARS
Enables tracing of TreeNode lifetimes in a set of output txt files.
Definition TreeNode.hpp:57
#define DIGIT_CHARS
Digit characters (for valid TreeNode groups)
Definition TreeNode.hpp:61
essentially a pass through notification source that is a placeholder in a shadow tree.
MirrorNotificationSource(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, const std::string *notification_name_id)
MirrorNotificationSource.
void addLink(TreeNode *node, const std::string &label) override final
MirrorNotificationSource(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, const std::string &notification_name)
Alternate construct that accepts a notification name string instead of an interned string pointer.
Controlled interface to NotificationSourceBase for regiistering and deregistering observation state c...
Callback for observation-state of a NotificationSourceBase.
void operator()(NotificationSourceBase const &ns, uint32_t observers) const
Invoked the callback function.
void dump(std::ostream &o) const
Dump string description to an ostream.
ObservationStateChange getType() const
Get tyhe type of change associated with this callback instance.
A TreeNode that generates a single specific type of notification which propagates up a tree of TreeNo...
virtual ~NotificationSourceBase()
Destructor.
static void validateNotificationName(const std::string &nm)
Validates the given notification name string.
std::function< void(NotificationSourceBase const &, uint32_t)> callback_t
Observation state change callback function signature.
bool observed_
Cached value of obs_nodes_.size() > 0 for faster queries.
friend class ObservationStateCallbackInterface
Allow controlled interaction with some members of this class.
bool canGenerateNotification_(const std::type_info &tinfo, const std::string *id, const std::string *&match) const override
Implements TreeNode::canGenerateNotification. Node subclasses which will post notifications must impl...
const std::string & getNotificationName() const
Returns the notification name string for slow string comparison or printing.
ObservationStateChange
Various hook types for which one can register internal callbacks on this notificaiton source.
@ SOLE_OBSERVER_REGISTERING
A sole observer is being registered to observe this notification source. This is a transition from 0 ...
@ OBSERVER_REGISTERING
An observer is being registered to observe this notification source. This may be the first,...
@ SOLE_OBSERVER_DEREGISTERING
A sole observer is being de-registered from observing this notification source. This is a transition ...
@ OBSERVER_DEREGISTERING
An observer is being de-registered from observing this notification source. This may be the first,...
uint32_t getNumObservers() const
Returns the number of delegates affected by postings of this notification.
std::vector< TreeNode * > obs_nodes_
Vector of TreeNodes at which the notification that this node can generate is being observed.
bool observed() const noexcept
Is this NotificationSourceBase being observed at this node or an ancestor of any distance.
virtual void notificationObserverRemoved_(const std::type_info &tinfo, const std::string *name_id, TreeNode *obs_node, const delegate *del) override
NotificationSourceBase(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, const std::string *notification_name_id, const std::type_info &notification_tinfo)
NotificationSourceBase.
virtual std::string stringize(bool pretty=false) const override
Create a string representation of this node.
const std::type_info & noti_tinfo_
Type of notification data.
virtual void notificationObserverAdded_(const std::type_info &tinfo, const std::string *name_id, TreeNode *obs_node, const delegate *del) override
uint64_t getNumPosts() const
Returns the number of notifications posted by this node.
NotificationSourceBase(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, const std::string &notification_name, const std::type_info &notification_tinfo)
Alternate construct that accepts a notification name string instead of an interned string pointer.
uint32_t getNumObservationPoints() const
Returns the number of observation points affecting this notification source.
const std::string getNotificationTypeName() const
Gets the demangled name of the C++ notification type which this NotificationSource can emit.
const std::vector< TreeNode * > & getObservationPoints() const
Returns the vector of observation points on this notification source.
const std::type_info & getNotificationType() const
Returns std::type_info from typeid() on the notification data type which this NotificationSource can ...
uint64_t num_posts_
Number of messages posted whether observed or not.
const std::string * noti_id_
Name of notification generated. Should be similar to node name.
std::vector< delegate > dels_
Vector of delegates directly observing this notification source.
const std::string * getNotificationID() const
Returns notification ID (string pointer from Notification ID interned in sparta::StringManager)
A TreeNode that generates a specific type of notification which propagates up a tree of TreeNodes (us...
void deregisterForThis(T *obj)
Deregisters a callback method that was registered with registerForThis.
NotificationDataT data_type
Type of notification data generated by this instance.
void postNotification(const NotificationDataT &data) const
Post with reference to data with parent as message origin.
void registerForThis(T *obj)
Registers a callback method to listen for the notification generated by this NotificationSource....
NotificationDataT const const_data_type
Const qualified data type.
NotificationSource(TreeNode *parent, const std::string &name, const std::string &group, TreeNode::group_idx_type group_idx, const std::string &desc, const std::string *notification_name_id)
NotificationSource.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
Manages string internment for SPARTA. This allows strings to be compared by pointer once interned.
static StringManager & getStringManager()
Returns the StringManager singleton.
Temporary delegate for notificaiton invokation until the implementation is working....
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
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
std::weak_ptr< const TreeNode > ConstWeakPtr
Weak pointer to a const TreeNode. Acquire with getWeakPtr.
Definition TreeNode.hpp:271
std::string getLocation() const override final
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
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.
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...
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
WeakPtr getWeakPtr()
Gets a weak pointer to this TreeNode. This weak pointer is guaranteed to expire when this TreeNode is...
static TreeNode * getVirtualGlobalNode()
Gets the virtual global node singleton. This node can have no parent and no children....
const std::string & getName() const override
Gets the name of this node.
std::vector< delegate > DelegateVector
Vector of delegates representing a list of observers to notify.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
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:203
Type for indicating that ANY notification source type should be included in a search performed by loc...
Definition TreeNode.hpp:290