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 "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);
}

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
// 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<Modifiable*, Notifier*> ModifiableMap;
typedef std::unordered_multimap<Modifiable*, Receiver*> 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

View file

@ -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);

View file

@ -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

View file

@ -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