2 * src/lemon/notifier.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H
18 #define LEMON_ALTERATION_OBSERVER_REGISTRY_H
25 ///\brief Observer registry for graph alteration observers.
29 /// \addtogroup graphmaps
32 /// Registry class to register objects observes alterations in the graph.
34 /// This class is a registry for the objects which observe the
35 /// alterations in a container. The alteration observers can be attached
36 /// to and detached from the registry. The observers have to inherit
37 /// from the \ref AlterationNotifier::ObserverBase and override
38 /// the virtual functions in that.
40 /// The most important application of the alteration observing is the
41 /// dynamic map implementation when the observers are observing the
42 /// alterations in the graph.
44 /// \param _Item The item type what the observers are observing, usually
47 /// \author Balazs Dezso
49 template <typename _Item>
50 class AlterationNotifier {
54 /// ObserverBase is the base class for the observers.
56 /// ObserverBase is the abstract base class for the observers.
57 /// It will be notified about an item was inserted into or
58 /// erased from the graph.
60 /// The observer interface contains some pure virtual functions
61 /// to override. The add() and erase() functions are
62 /// to notify the oberver when one item is added or
65 /// The build() and clear() members are to notify the observer
66 /// about the container is built from an empty container or
67 /// is cleared to an empty container.
69 /// \author Balazs Dezso
73 typedef AlterationNotifier Registry;
75 friend class AlterationNotifier;
77 /// Default constructor.
79 /// Default constructor for ObserverBase.
81 ObserverBase() : registry(0) {}
83 virtual ~ObserverBase() {}
85 /// Attaches the observer into an AlterationNotifier.
87 /// This member attaches the observer into an AlterationNotifier.
89 void attach(AlterationNotifier& r) {
91 registry->attach(*this);
94 /// Detaches the observer into an AlterationNotifier.
96 /// This member detaches the observer from an AlterationNotifier.
100 registry->detach(*this);
105 /// Gives back a pointer to the registry what the map attached into.
107 /// This function gives back a pointer to the registry what the map
110 Registry* getRegistry() const { return const_cast<Registry*>(registry); }
112 /// Gives back true when the observer is attached into a registry.
113 bool attached() const { return registry != 0; }
117 ObserverBase(const ObserverBase& copy);
118 ObserverBase& operator=(const ObserverBase& copy);
127 /// \brief The member function to notificate the observer about an
128 /// item is added to the container.
130 /// The add() member function notificates the observer about an item
131 /// is added to the container. It have to be overrided in the
134 virtual void add(const Item&) = 0;
137 /// \brief The member function to notificate the observer about an
138 /// item is erased from the container.
140 /// The erase() member function notificates the observer about an
141 /// item is erased from the container. It have to be overrided in
144 virtual void erase(const Item&) = 0;
146 /// \brief The member function to notificate the observer about the
147 /// container is built.
149 /// The build() member function notificates the observer about the
150 /// container is built from an empty container. It have to be
151 /// overrided in the subclasses.
153 virtual void build() = 0;
155 /// \brief The member function to notificate the observer about all
156 /// items are erased from the container.
158 /// The clear() member function notificates the observer about all
159 /// items are erased from the container. It have to be overrided in
162 virtual void clear() = 0;
169 typedef std::vector<ObserverBase*> Container;
176 /// Default constructor.
179 /// The default constructor of the AlterationNotifier.
180 /// It creates an empty registry.
181 AlterationNotifier() {}
183 /// Copy Constructor of the AlterationNotifier.
185 /// Copy constructor of the AlterationNotifier.
186 /// It creates only an empty registry because the copiable
187 /// registry's observers have to be registered still into that registry.
188 AlterationNotifier(const AlterationNotifier&) {}
192 /// Assign operator for the AlterationNotifier.
193 /// It makes the notifier only empty because the copiable
194 /// notifier's observers have to be registered still into that registry.
195 AlterationNotifier& operator=(const AlterationNotifier&) {
196 typename Container::iterator it;
197 for (it = container.begin(); it != container.end(); ++it) {
204 /// Destructor of the AlterationNotifier.
206 ~AlterationNotifier() {
207 typename Container::iterator it;
208 for (it = container.begin(); it != container.end(); ++it) {
216 void attach(ObserverBase& observer) {
217 container.push_back(&observer);
218 observer.registry = this;
219 observer.registry_index = container.size()-1;
222 void detach(ObserverBase& base) {
223 container.back()->registry_index = base.registry_index;
224 container[base.registry_index] = container.back();
225 container.pop_back();
231 /// Notifies all the registered observers about an Item added to the container.
233 /// It notifies all the registered observers about an Item added to the container.
235 void add(const Item& key) {
236 typename Container::iterator it;
237 for (it = container.begin(); it != container.end(); ++it) {
242 /// Notifies all the registered observers about an Item erased from the container.
244 /// It notifies all the registered observers about an Item erased from the container.
246 void erase(const Item& key) {
247 typename Container::iterator it;
248 for (it = container.begin(); it != container.end(); ++it) {
254 /// Notifies all the registered observers about the container is built.
256 /// Notifies all the registered observers about the container is built
257 /// from an empty container.
259 typename Container::iterator it;
260 for (it = container.begin(); it != container.end(); ++it) {
266 /// Notifies all the registered observers about all Items are erased.
268 /// Notifies all the registered observers about all Items are erased
269 /// from the container.
271 typename Container::iterator it;
272 for (it = container.begin(); it != container.end(); ++it) {
279 /// \brief Class to extend a graph with the functionality of alteration
282 /// AlterableGraphExtender extends the _Base graphs functionality with
283 /// the possibility of alteration observing. It defines two observer
284 /// registrys for the nodes and mapes.
286 /// \todo Document what "alteration observing" is. And probably find a
287 /// better (shorter) name.
289 /// \param _Base is the base class to extend.
291 /// \pre _Base is conform to the BaseGraphComponent concept.
293 /// \post AlterableGraphExtender<_Base> is conform to the
294 /// AlterableGraphComponent concept.
296 /// \author Balazs Dezso
298 template <typename _Base>
299 class AlterableGraphExtender : public _Base {
302 typedef AlterableGraphExtender Graph;
303 typedef _Base Parent;
305 typedef typename Parent::Node Node;
306 typedef typename Parent::Edge Edge;
308 /// The edge observer registry.
309 typedef AlterationNotifier<Edge> EdgeNotifier;
310 /// The node observer registry.
311 typedef AlterationNotifier<Node> NodeNotifier;
316 mutable EdgeNotifier edge_notifier;
318 mutable NodeNotifier node_notifier;
322 /// \brief Gives back the edge alteration notifier.
324 /// Gives back the edge alteration notifier.
325 EdgeNotifier& getNotifier(Edge) const {
326 return edge_notifier;
329 /// \brief Gives back the node alteration notifier.
331 /// Gives back the node alteration notifier.
332 NodeNotifier& getNotifier(Node) const {
333 return node_notifier;
336 ~AlterableGraphExtender() {
337 node_notifier.clear();
338 edge_notifier.clear();
343 /// \brief Class to extend an undirected graph with the functionality of
344 /// alteration observing.
348 /// \sa AlterableGraphExtender
350 /// \bug This should be done some other way. Possibilities: template
351 /// specialization (not very easy, if at all possible); some kind of
352 /// enable_if boost technique?
354 template <typename _Base>
355 class AlterableUndirGraphExtender
356 : public AlterableGraphExtender<_Base> {
359 typedef AlterableUndirGraphExtender Graph;
360 typedef AlterableGraphExtender<_Base> Parent;
362 typedef typename Parent::UndirEdge UndirEdge;
364 /// The edge observer registry.
365 typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
369 mutable UndirEdgeNotifier undir_edge_notifier;
373 using Parent::getNotifier;
374 UndirEdgeNotifier& getNotifier(UndirEdge) const {
375 return undir_edge_notifier;
378 ~AlterableUndirGraphExtender() {
379 undir_edge_notifier.clear();