11#include "sparta/utils/StringManager.hpp"
56 #define REGISTER_FOR_THIS(func) \
57 registerForThis<typename std::remove_reference<decltype(*this)>::type, \
58 &std::remove_reference<decltype(*this)>::type::func>(this);
65 #define DEREGISTER_FOR_THIS(func) \
66 deregisterForThis<typename std::remove_reference<decltype(*this)>::type, \
67 &std::remove_reference<decltype(*this)>::type::func>(this);
70 class MirrorNotificationSource;
177 ObservationStateCallbackPrivateInterface::registerObservationStateChangeCallback_(ns_,
this);
183 if (tree_node_weak_ptr_.expired() ==
false) {
184 ObservationStateCallbackPrivateInterface::deregisterObservationStateChangeCallback_(ns_,
this);
201 uint32_t observers)
const
203 callback_(ns, observers);
209 void dump(std::ostream& o)
const {
210 o <<
"<ObservationStateCallback type=" <<
static_cast<int>(type_) <<
" node=";
211 if(tree_node_weak_ptr_.expired()){
214 o << tree_node_weak_ptr_.lock()->getLocation();
229 ns.registerObservationStateChangeCallback_(cbobject);
236 ns.deregisterObservationStateChangeCallback_(cbobject);
270 const std::string& name,
271 const std::string& group,
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),
282 if(
nullptr == parent){
284 <<
getLocation() <<
" must be constructed with a parent";
289 if(
nullptr == notification_name_id){
291 <<
getLocation() <<
" cannot be constructed with a null notification_name_id";
301 determineObs_Nodes_();
309 const std::string& name,
310 const std::string& group,
312 const std::string& desc,
313 const std::string& notification_name,
314 const std::type_info& notification_tinfo) :
316 StringManager::getStringManager().internString(notification_name),
349 << nm <<
"\" is a reserved word. ";
353 if(nm.size() > 0 && nm[0] ==
'_'){
355 << nm <<
"\" begins with an '_' which is not permitted";
358 if(nm.find(
"__") != std::string::npos){
360 << nm <<
"\" contains two adjacent underscores which is not permitted";
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.";
370 if(pos != std::string::npos){
372 << nm <<
"\" contains a '" << nm[pos] <<
"', which is not permitted. "
373 <<
"A Notification name must contain only alphanumeric characters and underscores.";
496 const std::string* name_id,
511 dels_.push_back(*del);
517 if(not was_observed){
526 const std::string* name_id,
537 auto delitr = std::find(
dels_.begin(),
dels_.end(), *del);
538 if(delitr !=
dels_.end()){
545 bool remaining =
false;
547 if(d.getObservationPoint() == obs_node){
552 if(
false == remaining){
570 const std::string*
id,
571 const std::string*& match)
const override {
585 virtual std::string
stringize(
bool pretty=
false)
const override {
587 std::stringstream ss;
597 virtual void onAddedAsChild_() noexcept override final {
598 determineObs_Nodes_();
611 void determineObs_Nodes_() {
622 node = node->getParent();
637 void getPossibleNotifications_(std::vector<NotificationInfo>& infos)
const override {
644 void registerObservationStateChangeCallback_(ObservationStateCallback*
const hook) {
646 sparta_assert(in_observation_state_change_callback_ ==
false,
647 "cannot add observation state change callbacks from within a callback");
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);
656 obs_state_change_cbs_.emplace_back(hook);
662 void deregisterObservationStateChangeCallback_(ObservationStateCallback*
const hook) {
664 sparta_assert(in_observation_state_change_callback_ ==
false,
665 "cannot remove observation state change callbacks from within a callback");
667 const auto itr = std::find(obs_state_change_cbs_.begin(), obs_state_change_cbs_.end(), hook);
671 "Internal notification hook " << *hook
672 <<
" was not found while attemptint to deregister it from notification source " << *
this);
675 obs_state_change_cbs_.erase(itr);
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");
690 in_observation_state_change_callback_ =
true;
694 for(ObservationStateCallback
const * cb : obs_state_change_cbs_){
695 if(cb->getType() == to_call){
700 in_observation_state_change_callback_ =
false;
705 in_observation_state_change_callback_ =
false;
716 std::vector<ObservationStateCallback*> obs_state_change_cbs_;
726 bool in_observation_state_change_callback_ =
false;
738 template <
typename NotificationDataT>
763 const std::string& name,
764 const std::string& group,
766 const std::string& desc,
767 const std::string* notification_name_id) :
769 desc, notification_name_id,
770 typeid(NotificationDataT))
772 static_assert(std::is_same<
773 typename std::remove_cv<
774 typename std::remove_reference<
775 typename std::remove_pointer<NotificationDataT>::type
780 "NotificationDataT must NOT be a const, volatile, pointer, or reference"
781 "type. It violates at least one of these restrictions");
789 const std::string& name,
790 const std::string& group,
792 const std::string& desc,
793 const std::string& notification_name) :
799 StringManager::getStringManager().internString(notification_name))
805 NotificationSource(TreeNode* parent,
806 const std::string& name,
807 const std::string& desc,
808 const std::string* notification_name_id) :
809 NotificationSource(parent,
814 notification_name_id)
821 const std::string& name,
822 const std::string& desc,
823 const std::string& notification_name) :
829 StringManager::getStringManager().internString(notification_name))
836 const std::string& group,
838 const std::string& desc,
839 const std::string* notification_name_id) :
845 notification_name_id)
852 const std::string& group,
854 const std::string& desc,
855 const std::string& notification_name) :
861 StringManager::getStringManager().internString(notification_name))
920 template <
typename T,
void (T::*TMethod)(const TreeNode&, const TreeNode&, const_data_type&)>
922 sparta::TreeNode::registerForNotification<data_type, T, TMethod>(obj, *
noti_id_);
926 template <
typename T,
void (T::*TMethod)(const_data_type&)>
928 sparta::TreeNode::registerForNotification<data_type, T, TMethod>(obj, *
noti_id_);
939 template <
typename T,
void (T::*TMethod)(const TreeNode&, const TreeNode&, const_data_type&)>
941 sparta::TreeNode::deregisterForNotification<data_type, T, TMethod>(obj, *
noti_id_);
945 template <
typename T,
void (T::*TMethod)(const_data_type&)>
947 sparta::TreeNode::deregisterForNotification<data_type, T, TMethod>(obj, *
noti_id_);
987 template<
typename NotificationDataT>
990 typedef std::vector<NotificationSourceBase*> SrcList;
1008 const std::string& name,
1009 const std::string& group,
1011 const std::string& desc,
1012 const std::string* notification_name_id):
1014 notification_name_id,
1015 typeid(NotificationDataT))
1023 const std::string& name,
1024 const std::string& group,
1026 const std::string& desc,
1027 const std::string& notification_name) :
1031 typeid(NotificationDataT))
1036 const std::string& name,
1037 const std::string& desc,
1038 const std::string& notification_name) :
1044 StringManager::getStringManager().internString(notification_name))
1062 const uint32_t prev_size = concretes_.size();
1063 findMatchingSourcesBelowNode_(*node, concretes_);
1067 if (concretes_.size() - prev_size == 0)
1070 ex <<
getName() <<
"\" was unable to bind to any real NotificationSources"
1071 <<
" found under the nodes provided to addLink().";
1104 findMatchingSourcesBelowNode_(*n, bases);
1110 void notificationObserverAdded_(
const std::type_info& tinfo,
1111 const std::string* name_id,
1113 const delegate* del)
override final
1115 if (del->revealsOrigin())
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.";
1125 if (concretes_.size() == 0)
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_()";
1134 for(
auto concrete : concretes_)
1136 concrete->notificationObserverAdded_(tinfo, name_id,
1142 void notificationObserverRemoved_(
const std::type_info& tinfo,
1143 const std::string* name_id,
1145 const delegate* del)
override final
1147 if (concretes_.size() == 0)
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_()";
1157 for(
auto concrete : concretes_)
1159 concrete->notificationObserverRemoved_(tinfo, name_id,
1165 bool canGenerateNotification_(
const std::type_info& tinfo,
1166 const std::string*
id,
1167 const std::string*& match)
const override final
1169 if (concretes_.size() == 0)
1173 bool can_generate =
true;
1174 for (
auto noti_src : concretes_)
1176 can_generate &= noti_src->canGenerateNotification_(tinfo,
id, match);
1178 return can_generate;
1187 void validateNode_() const override final
1189 if (concretes_.size() == 0)
1191 SpartaException ex(
"Unbound MirrorNotificationSource ");
1192 ex <<
getName() <<
" was never bound to concrete notification sources.";
1198 virtual std::string stringize(
bool pretty=
false) const override final {
1200 std::stringstream ss;
1204 ss << concretes_.size() <<
" sources ";
1206 catch (SpartaException&)
1208 ss <<
"[UNAVAILABLE]";
1216 inline std::ostream&
operator<<(std::ostream& o,
const NotificationSourceBase::ObservationStateCallback& osc)
1222 inline std::ostream&
operator<<(std::ostream& o,
const NotificationSourceBase::ObservationStateCallback* osc)
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...
#define ALPHANUM_CHARS
Enables tracing of TreeNode lifetimes in a set of output txt files.
#define DIGIT_CHARS
Digit characters (for valid TreeNode groups)
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 ¬ification_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 ¬ification_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 ¬ification_name, const std::type_info ¬ification_tinfo)
Alternate construct that accepts a notification name string instead of an interned string pointer.
friend class MirrorNotificationSource
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.
~NotificationSource()
Destructor.
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.
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
std::weak_ptr< const TreeNode > ConstWeakPtr
Weak pointer to a const TreeNode. Acquire with getWeakPtr.
std::string getLocation() const override final
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
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.
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.
Type for indicating that ANY notification source type should be included in a search performed by loc...