diff --git a/src/StateAccess.cc b/src/StateAccess.cc index b580215271..dcf5ef8b21 100644 --- a/src/StateAccess.cc +++ b/src/StateAccess.cc @@ -1,37 +1,44 @@ -#include "Val.h" +// See the file "COPYING" in the main distribution directory for copyright. + #include "StateAccess.h" -#include "Event.h" -#include "NetVar.h" #include "DebugLogger.h" notifier::Registry notifier::registry; +notifier::Receiver::Receiver() + { + DBG_LOG(DBG_NOTIFIERS, "creating receiver %p", this); + } + +notifier::Receiver::~Receiver() + { + DBG_LOG(DBG_NOTIFIERS, "deleting receiver %p", this); + } + notifier::Registry::~Registry() { for ( auto i : registrations ) Unregister(i.first); } -void notifier::Registry::Register(Modifiable* m, notifier::Notifier* notifier) +void notifier::Registry::Register(Modifiable* m, notifier::Receiver* r) { - DBG_LOG(DBG_NOTIFIERS, "registering modifiable %p for notifier %p", - m, notifier); + DBG_LOG(DBG_NOTIFIERS, "registering object %p for receiver %p", m, r); - registrations.insert({m, notifier}); - ++m->notifiers; + registrations.insert({m, r}); + ++m->num_receivers; } -void notifier::Registry::Unregister(Modifiable* m, notifier::Notifier* notifier) +void notifier::Registry::Unregister(Modifiable* m, notifier::Receiver* r) { - DBG_LOG(DBG_NOTIFIERS, "unregistering modifiable %p from notifier %p", - m, notifier); + DBG_LOG(DBG_NOTIFIERS, "unregistering object %p from receiver %p", m, r); auto x = registrations.equal_range(m); for ( auto i = x.first; i != x.second; i++ ) { - if ( i->second == notifier ) + if ( i->second == r ) { - --i->first->notifiers; + --i->first->num_receivers; registrations.erase(i); break; } @@ -40,19 +47,18 @@ void notifier::Registry::Unregister(Modifiable* m, notifier::Notifier* notifier) void notifier::Registry::Unregister(Modifiable* m) { - DBG_LOG(DBG_NOTIFIERS, "unregistering modifiable %p from all notifiers", - m); + DBG_LOG(DBG_NOTIFIERS, "unregistering object %p from all notifiers", m); auto x = registrations.equal_range(m); for ( auto i = x.first; i != x.second; i++ ) - --i->first->notifiers; + --i->first->num_receivers; registrations.erase(x.first, x.second); } void notifier::Registry::Modified(Modifiable* m) { - DBG_LOG(DBG_NOTIFIERS, "modification to modifiable %p", m); + DBG_LOG(DBG_NOTIFIERS, "object %p has been modified", m); auto x = registrations.equal_range(m); for ( auto i = x.first; i != x.second; i++ ) @@ -61,6 +67,6 @@ void notifier::Registry::Modified(Modifiable* m) notifier::Modifiable::~Modifiable() { - if ( notifiers ) + if ( num_receivers ) registry.Unregister(this); } diff --git a/src/StateAccess.h b/src/StateAccess.h index b769e320c0..2361801ec4 100644 --- a/src/StateAccess.h +++ b/src/StateAccess.h @@ -1,14 +1,9 @@ -// A class describing a state-modyfing access to a Value or an ID. +// See the file "COPYING" in the main distribution directory for copyright. // -// TODO UPDATE: We provide a notifier framework to inform interested parties -// of modifications to selected global IDs/Vals. To get notified about a -// change, derive a class from Notifier and register the interesting -// instances with the NotifierRegistry. -// -// Note: For containers (e.g., tables), notifications are only issued if the -// container itself is modified, *not* for changes to the values contained -// therein. - +// A notification framework to inform interested parties of modifications to +// selected global objects. To get notified about a change, derive a class +// from notifier::Receiver and register the interesting objects with the +// notification::Registry. #ifndef STATEACESSS_H #define STATEACESSS_H @@ -24,70 +19,98 @@ namespace notifier { class Modifiable; -class Notifier { +/** Interface class for receivers of notifications. */ +class Receiver { public: - Notifier() - { - DBG_LOG(DBG_NOTIFIERS, "creating notifier %p", this); - } + Receiver(); + virtual ~Receiver(); - virtual ~Notifier() - { - DBG_LOG(DBG_NOTIFIERS, "destroying notifier %p", this); - } - - // Called after a change has been performed. + /** + * Callback executed when a register object has been modified. + * + * @param m object that was modified + */ virtual void Modified(Modifiable* m) = 0; }; -// Singleton class. +/** Singleton class tracking all notification requests globally. */ class Registry { public: - Registry() { } ~Registry(); - // Register a new notifier to be informed when an instance changes. - void Register(Modifiable* m, Notifier* notifier); + /** + * Registers a receiver to be informed when a modifiable object has + * changed. + * + * @param m object to track. Does not take ownership, but the object + * will automatically unregister itself on destruction. + * + * @param r receiver to notify on changes. Does not take ownershop, + * the receiver must remain valid as long as the registration stays + * in place. + */ + void Register(Modifiable* m, Receiver* r); - // Cancel a notifier's tracking an instace. - void Unregister(Modifiable* m, Notifier* notifier); + /** + * Cancels a receiver's request to be informed about an object's + * modification. The arguments to the method must match what was + * originally registered. + * + * @param m object to no loger track. + * + * @param r receiver to no longer notify. + */ + void Unregister(Modifiable* m, Receiver* Receiver); - // Cancel all notifiers registered for an instance. + /** + * Cancels any active receiver requests to be informed about a + * partilar object's modifications. + * + * @param m object to no loger track. + */ void Unregister(Modifiable* m); private: friend class Modifiable; - // Inform all registered notifiers of a modification to an instance. + // Inform all registered receivers of a modification to an object. + // Will be called from the object itself. void Modified(Modifiable* m); - typedef std::unordered_multimap ModifiableMap; + typedef std::unordered_multimap ModifiableMap; ModifiableMap registrations; }; - -class Registry; +/** + * Singleton object tracking all global notification requests. + */ extern Registry registry; -// Base class for objects wanting to signal modifications to the registry. +/** + * Base class for objects that can trigger notifications to receivers when + * modified. + */ class Modifiable { -protected: - friend class Registry; - - Modifiable() {} - virtual ~Modifiable(); - +public: + /** + * Calling this method signals to all registered receivers that the + * object has been modified. + */ void Modified() { - if ( notifiers ) + if ( num_receivers ) registry.Modified(this); } - // Number of currently registered notifiers for this instance. - uint64 notifiers; +protected: + friend class Registry; + + virtual ~Modifiable(); + + // Number of currently registered receivers. + uint64 num_receivers; }; } - #endif diff --git a/src/Trigger.cc b/src/Trigger.cc index 8de5dff5bd..ae6483e3f5 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -404,7 +404,7 @@ void Trigger::UnregisterAll() { DBG_LOG(DBG_NOTIFIERS, "%s: unregistering all", Name()); - for ( auto o : objs ) + for ( const auto& o : objs ) { notifier::registry.Unregister(o.second, this); Unref(o.first); diff --git a/src/Trigger.h b/src/Trigger.h index 3004d30732..0de5499045 100644 --- a/src/Trigger.h +++ b/src/Trigger.h @@ -13,7 +13,7 @@ class TriggerTimer; class TriggerTraversalCallback; -class Trigger : public notifier::Notifier, public BroObj { +class Trigger : public BroObj, public notifier::Receiver { public: // Don't access Trigger objects; they take care of themselves after // instantiation. Note that if the condition is already true, the diff --git a/src/Val.h b/src/Val.h index 48bbd50cfc..8eb33d1f0e 100644 --- a/src/Val.h +++ b/src/Val.h @@ -322,6 +322,8 @@ public: void Describe(ODesc* d) const override; virtual void DescribeReST(ODesc* d) const; + // To be overridden by mutable derived class to enable change + // notification. virtual notifier::Modifiable* Modifiable() { return 0; } #ifdef DEBUG