diff -r d8475431bbbb -r 8e85e6bbefdf lemon/bits/alteration_notifier.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/alteration_notifier.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,438 @@ +/* -*- C++ -*- + * lemon/notifier.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H +#define LEMON_ALTERATION_OBSERVER_REGISTRY_H + +#include +#include + +///\ingroup graphmaps +///\file +///\brief Observer registry for graph alteration observers. + +namespace lemon { + + /// \addtogroup graphmaps + /// @{ + + /// \brief Registry class to register objects observes alterations in + /// the graph. + /// + /// This class is a registry for the objects which observe the + /// alterations in a container. The alteration observers can be attached + /// to and detached from the registry. The observers have to inherit + /// from the \ref AlterationNotifier::ObserverBase and override + /// the virtual functions in that. + /// + /// The most important application of the alteration observing is the + /// dynamic map implementation. + /// + /// \param _Item The item type what the observers are observing, usually + /// edge or node. + /// + /// \author Balazs Dezso + + template + class AlterationNotifier { + public: + typedef _Item Item; + + /// ObserverBase is the base class for the observers. + + /// ObserverBase is the abstract base class for the observers. + /// It will be notified about an item was inserted into or + /// erased from the graph. + /// + /// The observer interface contains some pure virtual functions + /// to override. The add() and erase() functions are + /// to notify the oberver when one item is added or + /// erased. + /// + /// The build() and clear() members are to notify the observer + /// about the container is built from an empty container or + /// is cleared to an empty container. + /// + /// \author Balazs Dezso + + class ObserverBase { + protected: + typedef AlterationNotifier Registry; + + friend class AlterationNotifier; + + /// \brief Default constructor. + /// + /// Default constructor for ObserverBase. + /// + ObserverBase() : registry(0) {} + + virtual ~ObserverBase() {} + + /// \brief Attaches the observer into an AlterationNotifier. + /// + /// This member attaches the observer into an AlterationNotifier. + /// + void attach(AlterationNotifier& r) { + registry = &r; + registry->attach(*this); + } + + /// \brief Detaches the observer into an AlterationNotifier. + /// + /// This member detaches the observer from an AlterationNotifier. + /// + void detach() { + if (registry) { + registry->detach(*this); + } + } + + + /// Gives back a pointer to the registry what the map attached into. + + /// This function gives back a pointer to the registry what the map + /// attached into. + /// + Registry* getRegistry() const { return const_cast(registry); } + + /// Gives back true when the observer is attached into a registry. + bool attached() const { return registry != 0; } + + private: + + ObserverBase(const ObserverBase& copy); + ObserverBase& operator=(const ObserverBase& copy); + + protected: + + Registry* registry; + int registry_index; + + public: + + /// \brief The member function to notificate the observer about an + /// item is added to the container. + /// + /// The add() member function notificates the observer about an item + /// is added to the container. It have to be overrided in the + /// subclasses. + + virtual void add(const Item&) = 0; + + /// \brief The member function to notificate the observer about + /// simulitem is added to the container. + /// + /// The add() member function notificates the observer about an item + /// is added to the container. It have to be overrided in the + /// subclasses. + + virtual void add(const std::vector& items) { + for (int i = 0; i < (int)items.size(); ++i) { + add(items[i]); + } + } + + /// \brief The member function to notificate the observer about an + /// item is erased from the container. + /// + /// The erase() member function notificates the observer about an + /// item is erased from the container. It have to be overrided in + /// the subclasses. + + virtual void erase(const Item&) = 0; + + virtual void erase(const std::vector& items) { + for (int i = 0; i < (int)items.size(); ++i) { + add(items[i]); + } + } + + /// \brief The member function to notificate the observer about the + /// container is built. + /// + /// The build() member function notificates the observer about the + /// container is built from an empty container. It have to be + /// overrided in the subclasses. + + virtual void build() = 0; + + /// \brief The member function to notificate the observer about all + /// items are erased from the container. + /// + /// The clear() member function notificates the observer about all + /// items are erased from the container. It have to be overrided in + /// the subclasses. + + virtual void clear() = 0; + + }; + + protected: + + + typedef std::vector Container; + + Container container; + + + public: + + /// Default constructor. + + /// + /// The default constructor of the AlterationNotifier. + /// It creates an empty registry. + AlterationNotifier() {} + + /// Copy Constructor of the AlterationNotifier. + + /// Copy constructor of the AlterationNotifier. + /// It creates only an empty registry because the copiable + /// registry's observers have to be registered still into that registry. + AlterationNotifier(const AlterationNotifier&) {} + + /// Assign operator. + + /// Assign operator for the AlterationNotifier. + /// It makes the notifier only empty because the copiable + /// notifier's observers have to be registered still into that registry. + AlterationNotifier& operator=(const AlterationNotifier&) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->registry = 0; + } + } + + /// Destructor. + + /// Destructor of the AlterationNotifier. + /// + ~AlterationNotifier() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->registry = 0; + } + } + + + protected: + + void attach(ObserverBase& observer) { + container.push_back(&observer); + observer.registry = this; + observer.registry_index = container.size()-1; + } + + void detach(ObserverBase& base) { + container.back()->registry_index = base.registry_index; + container[base.registry_index] = container.back(); + container.pop_back(); + base.registry = 0; + } + + public: + + /// \brief Notifies all the registered observers about an Item added to + /// the container. + /// + /// It notifies all the registered observers about an Item added to + /// the container. + /// + void add(const Item& item) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->add(item); + } + } + + /// \brief Notifies all the registered observers about more Item added to + /// the container. + /// + /// It notifies all the registered observers about more Item added to + /// the container. + /// + void add(const std::vector& items) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->add(items); + } + } + + /// \brief Notifies all the registered observers about an Item erased from + /// the container. + /// + /// It notifies all the registered observers about an Item erased from + /// the container. + /// + void erase(const Item& key) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->erase(key); + } + } + + /// \brief Notifies all the registered observers about more Item erased + /// from the container. + /// + /// It notifies all the registered observers about more Item erased from + /// the container. + /// + void erase(const std::vector& items) { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->erase(items); + } + } + + + /// \brief Notifies all the registered observers about the container is + /// built. + /// + /// Notifies all the registered observers about the container is built + /// from an empty container. + void build() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->build(); + } + } + + + /// \brief Notifies all the registered observers about all Items are + /// erased. + /// + /// Notifies all the registered observers about all Items are erased + /// from the container. + void clear() { + typename Container::iterator it; + for (it = container.begin(); it != container.end(); ++it) { + (*it)->clear(); + } + } + }; + + + /// \brief Class to extend a graph with the functionality of alteration + /// observing. + /// + /// AlterableGraphExtender extends the _Base graphs functionality with + /// the possibility of alteration observing. It defines two observer + /// registrys for the nodes and mapes. + /// + /// \todo Document what "alteration observing" is. And probably find a + /// better (shorter) name. + /// + /// \param _Base is the base class to extend. + /// + /// \pre _Base is conform to the BaseGraphComponent concept. + /// + /// \post AlterableGraphExtender<_Base> is conform to the + /// AlterableGraphComponent concept. + /// + /// \author Balazs Dezso + + template + class AlterableGraphExtender : public _Base { + public: + + typedef AlterableGraphExtender Graph; + typedef _Base Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + /// The edge observer registry. + typedef AlterationNotifier EdgeNotifier; + /// The node observer registry. + typedef AlterationNotifier NodeNotifier; + + + protected: + + mutable EdgeNotifier edge_notifier; + + mutable NodeNotifier node_notifier; + + public: + + /// \brief Gives back the edge alteration notifier. + /// + /// Gives back the edge alteration notifier. + EdgeNotifier& getNotifier(Edge) const { + return edge_notifier; + } + + /// \brief Gives back the node alteration notifier. + /// + /// Gives back the node alteration notifier. + NodeNotifier& getNotifier(Node) const { + return node_notifier; + } + + ~AlterableGraphExtender() { + node_notifier.clear(); + edge_notifier.clear(); + } + + }; + + /// \brief Class to extend an undirected graph with the functionality of + /// alteration observing. + /// + /// \todo Document. + /// + /// \sa AlterableGraphExtender + /// + /// \bug This should be done some other way. Possibilities: template + /// specialization (not very easy, if at all possible); some kind of + /// enable_if boost technique? + + template + class AlterableUndirGraphExtender + : public AlterableGraphExtender<_Base> { + public: + + typedef AlterableUndirGraphExtender Graph; + typedef AlterableGraphExtender<_Base> Parent; + + typedef typename Parent::UndirEdge UndirEdge; + + /// The edge observer registry. + typedef AlterationNotifier UndirEdgeNotifier; + + protected: + + mutable UndirEdgeNotifier undir_edge_notifier; + + public: + + using Parent::getNotifier; + UndirEdgeNotifier& getNotifier(UndirEdge) const { + return undir_edge_notifier; + } + + ~AlterableUndirGraphExtender() { + undir_edge_notifier.clear(); + } + }; + +/// @} + + +} + +#endif