Clean up new code.

This commit is contained in:
Robin Sommer 2019-06-07 23:38:25 +00:00
parent 7bd738865c
commit 6adab8d46a
5 changed files with 94 additions and 63 deletions

View file

@ -1,37 +1,44 @@
#include "Val.h" // See the file "COPYING" in the main distribution directory for copyright.
#include "StateAccess.h" #include "StateAccess.h"
#include "Event.h"
#include "NetVar.h"
#include "DebugLogger.h" #include "DebugLogger.h"
notifier::Registry notifier::registry; 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() notifier::Registry::~Registry()
{ {
for ( auto i : registrations ) for ( auto i : registrations )
Unregister(i.first); 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", DBG_LOG(DBG_NOTIFIERS, "registering object %p for receiver %p", m, r);
m, notifier);
registrations.insert({m, notifier}); registrations.insert({m, r});
++m->notifiers; ++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", DBG_LOG(DBG_NOTIFIERS, "unregistering object %p from receiver %p", m, r);
m, notifier);
auto x = registrations.equal_range(m); auto x = registrations.equal_range(m);
for ( auto i = x.first; i != x.second; i++ ) 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); registrations.erase(i);
break; break;
} }
@ -40,19 +47,18 @@ void notifier::Registry::Unregister(Modifiable* m, notifier::Notifier* notifier)
void notifier::Registry::Unregister(Modifiable* m) void notifier::Registry::Unregister(Modifiable* m)
{ {
DBG_LOG(DBG_NOTIFIERS, "unregistering modifiable %p from all notifiers", DBG_LOG(DBG_NOTIFIERS, "unregistering object %p from all notifiers", m);
m);
auto x = registrations.equal_range(m); auto x = registrations.equal_range(m);
for ( auto i = x.first; i != x.second; i++ ) for ( auto i = x.first; i != x.second; i++ )
--i->first->notifiers; --i->first->num_receivers;
registrations.erase(x.first, x.second); registrations.erase(x.first, x.second);
} }
void notifier::Registry::Modified(Modifiable* m) 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); auto x = registrations.equal_range(m);
for ( auto i = x.first; i != x.second; i++ ) for ( auto i = x.first; i != x.second; i++ )
@ -61,6 +67,6 @@ void notifier::Registry::Modified(Modifiable* m)
notifier::Modifiable::~Modifiable() notifier::Modifiable::~Modifiable()
{ {
if ( notifiers ) if ( num_receivers )
registry.Unregister(this); registry.Unregister(this);
} }

View file

@ -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 // A notification framework to inform interested parties of modifications to
// of modifications to selected global IDs/Vals. To get notified about a // selected global objects. To get notified about a change, derive a class
// change, derive a class from Notifier and register the interesting // from notifier::Receiver and register the interesting objects with the
// instances with the NotifierRegistry. // notification::Registry.
//
// Note: For containers (e.g., tables), notifications are only issued if the
// container itself is modified, *not* for changes to the values contained
// therein.
#ifndef STATEACESSS_H #ifndef STATEACESSS_H
#define STATEACESSS_H #define STATEACESSS_H
@ -24,70 +19,98 @@ namespace notifier {
class Modifiable; class Modifiable;
class Notifier { /** Interface class for receivers of notifications. */
class Receiver {
public: public:
Notifier() Receiver();
{ virtual ~Receiver();
DBG_LOG(DBG_NOTIFIERS, "creating notifier %p", this);
}
virtual ~Notifier() /**
{ * Callback executed when a register object has been modified.
DBG_LOG(DBG_NOTIFIERS, "destroying notifier %p", this); *
} * @param m object that was modified
*/
// Called after a change has been performed.
virtual void Modified(Modifiable* m) = 0; virtual void Modified(Modifiable* m) = 0;
}; };
// Singleton class. /** Singleton class tracking all notification requests globally. */
class Registry { class Registry {
public: public:
Registry() { }
~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); void Unregister(Modifiable* m);
private: private:
friend class Modifiable; 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); void Modified(Modifiable* m);
typedef std::unordered_multimap<Modifiable*, Notifier*> ModifiableMap; typedef std::unordered_multimap<Modifiable*, Receiver*> ModifiableMap;
ModifiableMap registrations; ModifiableMap registrations;
}; };
/**
class Registry; * Singleton object tracking all global notification requests.
*/
extern Registry registry; 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 { class Modifiable {
protected: public:
friend class Registry; /**
* Calling this method signals to all registered receivers that the
Modifiable() {} * object has been modified.
virtual ~Modifiable(); */
void Modified() void Modified()
{ {
if ( notifiers ) if ( num_receivers )
registry.Modified(this); registry.Modified(this);
} }
// Number of currently registered notifiers for this instance. protected:
uint64 notifiers; friend class Registry;
virtual ~Modifiable();
// Number of currently registered receivers.
uint64 num_receivers;
}; };
} }
#endif #endif

View file

@ -404,7 +404,7 @@ void Trigger::UnregisterAll()
{ {
DBG_LOG(DBG_NOTIFIERS, "%s: unregistering all", Name()); DBG_LOG(DBG_NOTIFIERS, "%s: unregistering all", Name());
for ( auto o : objs ) for ( const auto& o : objs )
{ {
notifier::registry.Unregister(o.second, this); notifier::registry.Unregister(o.second, this);
Unref(o.first); Unref(o.first);

View file

@ -13,7 +13,7 @@
class TriggerTimer; class TriggerTimer;
class TriggerTraversalCallback; class TriggerTraversalCallback;
class Trigger : public notifier::Notifier, public BroObj { class Trigger : public BroObj, public notifier::Receiver {
public: public:
// Don't access Trigger objects; they take care of themselves after // Don't access Trigger objects; they take care of themselves after
// instantiation. Note that if the condition is already true, the // instantiation. Note that if the condition is already true, the

View file

@ -322,6 +322,8 @@ public:
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
virtual void DescribeReST(ODesc* d) const; virtual void DescribeReST(ODesc* d) const;
// To be overridden by mutable derived class to enable change
// notification.
virtual notifier::Modifiable* Modifiable() { return 0; } virtual notifier::Modifiable* Modifiable() { return 0; }
#ifdef DEBUG #ifdef DEBUG