/* -*- C++ -*- * src/lemon/observer_registry.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Combinatorial Optimization Research Group, 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. using namespace std; namespace lemon { /// \addtogroup graphmaps /// @{ /// 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 AlterationObserverRegistry::ObserverBase and override /// the virtual functions in that. /// /// The most important application of the alteration observing is the /// dynamic map implementation when the observers are observing the /// alterations in the graph. /// /// \param _Item The item type what the observers are observing, usually /// edge or node. /// /// \author Balazs Dezso template class AlterationObserverRegistry { 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 builded from an empty container or /// is cleared to an empty container. /// /// \author Balazs Dezso class ObserverBase { protected: typedef AlterationObserverRegistry Registry; friend class Registry; /// Default constructor. /// Default constructor for ObserverBase. /// ObserverBase() : registry(0) {} virtual ~ObserverBase() {} /// Attaches the observer into an AlterationObserverRegistry. /// This member attaches the observer into an AlterationObserverRegistry. /// void attach(AlterationObserverRegistry& r) { registry = &r; registry->attach(*this); } /// Detaches the observer into an AlterationObserverRegistry. /// This member detaches the observer from an AlterationObserverRegistry. /// 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 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; /// \brief The member function to notificate the observer about the /// container is builded. /// /// The build() member function notificates the observer about the /// container is builded 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 AlterationObserverRegistry. /// It creates an empty registry. AlterationObserverRegistry() {} /// Copy Constructor of the AlterationObserverRegistry. /// Copy constructor of the AlterationObserverRegistry. /// It creates only an empty registry because the copiable /// registry's observers have to be registered still into that registry. AlterationObserverRegistry(const AlterationObserverRegistry&) {} /// Assign operator. /// Assign operator for the AlterationObserverRegistry. /// It makes the registry only empty because the copiable /// registry's observers have to be registered still into that registry. AlterationObserverRegistry& operator=(const AlterationObserverRegistry&) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->registry = 0; } } /// Destructor. /// Destructor of the AlterationObserverRegistry. /// ~AlterationObserverRegistry() { 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: /// 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& key) { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->add(key); } } /// 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); } } /// Notifies all the registered observers about the container is builded. /// Notifies all the registered observers about the container is builded /// from an empty container. void build() { typename Container::iterator it; for (it = container.begin(); it != container.end(); ++it) { (*it)->build(); } } /// 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 AlterationObserverRegistry EdgeObserverRegistry; /// The node observer registry. typedef AlterationObserverRegistry NodeObserverRegistry; protected: mutable EdgeObserverRegistry edge_observers; mutable NodeObserverRegistry node_observers; public: EdgeObserverRegistry& getEdgeObserverRegistry() const { return edge_observers; } NodeObserverRegistry& getNodeObserverRegistry() const { return node_observers; } ~AlterableGraphExtender() { node_observers.clear(); edge_observers.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 AlterationObserverRegistry UndirEdgeObserverRegistry; protected: mutable UndirEdgeObserverRegistry undir_edge_observers; UndirEdgeObserverRegistry& getUndirEdgeObserverRegistry() const { return undir_edge_observers; } ~AlterableUndirGraphExtender() { undir_edge_observers.clear(); } }; /// @} } #endif