[Lemon-commits] [lemon_svn] deba: r2927 - in hugo/trunk/lemon: . bits

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 21:51:17 CET 2006


Author: deba
Date: Wed Sep  6 12:19:57 2006
New Revision: 2927

Added:
   hugo/trunk/lemon/bits/debug_map.h
Modified:
   hugo/trunk/lemon/Makefile.am
   hugo/trunk/lemon/bits/array_map.h
   hugo/trunk/lemon/bits/default_map.h
   hugo/trunk/lemon/bits/vector_map.h

Log:
New map type based on array map for debugging purpose

It checks multiple allocation and deallocation of map values and
some consistency.

todo: 
clarification of debugging concepts
assertions - exceptions - debug
revision of attic/debug.h

motto:
testing is at least so important as coding



Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am	(original)
+++ hugo/trunk/lemon/Makefile.am	Wed Sep  6 12:19:57 2006
@@ -100,6 +100,7 @@
 	lemon/bits/array_map.h \
 	lemon/bits/base_extender.h \
 	lemon/bits/bezier.h \
+	lemon/bits/debug_map.h \
 	lemon/bits/default_map.h \
 	lemon/bits/edge_set_extender.h \
 	lemon/bits/graph_adaptor_extender.h \

Modified: hugo/trunk/lemon/bits/array_map.h
==============================================================================
--- hugo/trunk/lemon/bits/array_map.h	(original)
+++ hugo/trunk/lemon/bits/array_map.h	Wed Sep  6 12:19:57 2006
@@ -41,7 +41,7 @@
   /// the map. This map uses the allocators to implement 
   /// the container functionality.
   ///
-  /// The template parameter is the Graph the current Item type and
+  /// The template parameters are the Graph the current Item type and
   /// the Value type of the map.
   template <typename _Graph, typename _Item, typename _Value>
   class ArrayMap 

Added: hugo/trunk/lemon/bits/debug_map.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/bits/debug_map.h	Wed Sep  6 12:19:57 2006
@@ -0,0 +1,378 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * 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_BITS_DEBUG_MAP_H
+#define LEMON_BITS_DEBUG_MAP_H
+
+#include <vector>
+#include <algorithm>
+
+#include <lemon/bits/traits.h>
+#include <lemon/bits/utility.h>
+#include <lemon/error.h>
+
+#include <lemon/bits/alteration_notifier.h>
+
+#include <lemon/concept_check.h>
+#include <lemon/concept/maps.h>
+
+///\ingroup graphbits
+///
+///\file
+///\brief Vector based graph maps for debugging.
+namespace lemon {
+
+  /// \ingroup graphbits
+  ///
+  /// \brief Graph map based on the std::vector storage.
+  ///
+  /// The DebugMap template class is graph map structure what
+  /// automatically updates the map when a key is added to or erased from
+  /// the map. This map also checks some programming failures by example
+  /// multiple addition of items, erasing of not existing item or
+  /// not erased items at the destruction of the map. It helps the
+  /// programmer to avoid segmentation faults and memory leaks.
+  ///
+  /// \param Notifier The AlterationNotifier that will notify this map.
+  /// \param Item The item type of the graph items.
+  /// \param Value The value type of the map.
+  /// 
+  /// \author Balazs Dezso  	
+  template <typename _Graph, typename _Item, typename _Value>
+  class DebugMap 
+    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
+  private:
+		
+    /// The container type of the map.
+    typedef std::vector<_Value> Container;	
+
+    /// The container type of the debug flags.
+    typedef std::vector<bool> Flag;	
+
+  public:
+
+    static const bool strictCheck = true;
+
+    struct MapError {
+    public:
+      virtual ~MapError() {}
+      virtual const char* what() const throw() {
+        return "lemon::DebugMap::MapError";
+      }
+    };
+
+    /// The graph type of the map. 
+    typedef _Graph Graph;
+    /// The item type of the map.
+    typedef _Item Item;
+    /// The reference map tag.
+    typedef True ReferenceMapTag;
+
+    /// The key type of the map.
+    typedef _Item Key;
+    /// The value type of the map.
+    typedef _Value Value;
+
+    /// The notifier type.
+    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
+
+    /// The map type.
+    typedef DebugMap Map;
+    /// The base class of the map.
+    typedef typename Notifier::ObserverBase Parent;
+
+    /// The reference type of the map;
+    typedef typename Container::reference Reference;
+    /// The const reference type of the map;
+    typedef typename Container::const_reference ConstReference;
+
+
+    /// \brief Constructor to attach the new map into the notifier.
+    ///
+    /// It constructs a map and attachs it into the notifier.
+    /// It adds all the items of the graph to the map.
+    DebugMap(const Graph& graph) {
+      Parent::attach(graph.getNotifier(Item()));
+      container.resize(Parent::getNotifier()->maxId() + 1);
+      flag.resize(Parent::getNotifier()->maxId() + 1, false);
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        flag[Parent::getNotifier()->id(it)] = true;
+      }
+    }
+
+    /// \brief Constructor uses given value to initialize the map. 
+    ///
+    /// It constructs a map uses a given value to initialize the map. 
+    /// It adds all the items of the graph to the map.
+    DebugMap(const Graph& graph, const Value& value) {
+      Parent::attach(graph.getNotifier(Item()));
+      container.resize(Parent::getNotifier()->maxId() + 1, value);
+      flag.resize(Parent::getNotifier()->maxId() + 1, false);
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        flag[Parent::getNotifier()->id(it)] = true;
+      }
+    }
+
+    /// \brief Copy constructor
+    ///
+    /// Copy constructor.
+    DebugMap(const DebugMap& _copy) : Parent() {
+      if (_copy.attached()) {
+	Parent::attach(*_copy.getNotifier());
+	container = _copy.container;
+      }
+      flag.resize(Parent::getNotifier()->maxId() + 1, false);
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        flag[Parent::getNotifier()->id(it)] = true;
+        LEMON_ASSERT(_copy.flag[Parent::getNotifier()->id(it)], MapError());
+      }
+    }
+
+    /// \brief Destructor
+    ///
+    /// Destructor.
+    ~DebugMap() {
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      if (notifier != 0) {
+        Item it;
+        for (notifier->first(it); it != INVALID; notifier->next(it)) {
+          LEMON_ASSERT(flag[Parent::getNotifier()->id(it)], MapError());
+          flag[Parent::getNotifier()->id(it)] = false;
+        }
+      }
+      for (int i = 0; i < (int)flag.size(); ++i) {
+        LEMON_ASSERT(!flag[i], MapError());
+      }
+    }
+
+    /// \brief Assign operator.
+    ///
+    /// This operator assigns for each item in the map the
+    /// value mapped to the same item in the copied map.  
+    /// The parameter map should be indiced with the same
+    /// itemset because this assign operator does not change
+    /// the container of the map. 
+    DebugMap& operator=(const DebugMap& cmap) {
+      return operator=<DebugMap>(cmap);
+    }
+
+
+    /// \brief Template assign operator.
+    ///
+    /// The given parameter should be conform to the ReadMap
+    /// concecpt and could be indiced by the current item set of
+    /// the NodeMap. In this case the value for each item
+    /// is assigned by the value of the given ReadMap. 
+    template <typename CMap>
+    DebugMap& operator=(const CMap& cmap) {
+      checkConcept<concept::ReadMap<Key, _Value>, CMap>();
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        set(it, cmap[it]);
+      }
+      return *this;
+    }
+    
+  public:
+
+    /// \brief The subcript operator.
+    ///
+    /// The subscript operator. The map can be subscripted by the
+    /// actual items of the graph.      
+    Reference operator[](const Key& key) {
+      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
+      return container[Parent::getNotifier()->id(key)];
+    } 
+		
+    /// \brief The const subcript operator.
+    ///
+    /// The const subscript operator. The map can be subscripted by the
+    /// actual items of the graph. 
+    ConstReference operator[](const Key& key) const {
+      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
+      return container[Parent::getNotifier()->id(key)];
+    }
+
+
+    /// \brief The setter function of the map.
+    ///
+    /// It the same as operator[](key) = value expression.
+    void set(const Key& key, const Value& value) {
+      (*this)[key] = value;
+    }
+
+  protected:
+
+    /// \brief Adds a new key to the map.
+    ///		
+    /// It adds a new key to the map. It called by the observer notifier
+    /// and it overrides the add() member function of the observer base.     
+    virtual void add(const Key& key) {
+      int id = Parent::getNotifier()->id(key);
+      if (id >= (int)container.size()) {
+	container.resize(id + 1);
+        flag.resize(id + 1, false);
+      }
+      LEMON_ASSERT(!flag[Parent::getNotifier()->id(key)], MapError());
+      flag[Parent::getNotifier()->id(key)] = true;
+      if (strictCheck) {
+        std::vector<bool> fl(flag.size(), false);
+        const typename Parent::Notifier* notifier = Parent::getNotifier();
+        Item it;
+        for (notifier->first(it); it != INVALID; notifier->next(it)) {
+          int id = Parent::getNotifier()->id(it);
+          fl[id] = true;
+        }
+        LEMON_ASSERT(fl == flag, MapError());
+      }
+    }
+
+    /// \brief Adds more new keys to the map.
+    ///		
+    /// It adds more new keys to the map. It called by the observer notifier
+    /// and it overrides the add() member function of the observer base.     
+    virtual void add(const std::vector<Key>& keys) {
+      int max = container.size() - 1;
+      for (int i = 0; i < (int)keys.size(); ++i) {
+        int id = Parent::getNotifier()->id(keys[i]);
+        if (id >= max) {
+          max = id;
+        }
+      }
+      container.resize(max + 1);
+      flag.resize(max + 1, false);
+      for (int i = 0; i < (int)keys.size(); ++i) {
+        LEMON_ASSERT(!flag[Parent::getNotifier()->id(keys[i])], MapError());
+        flag[Parent::getNotifier()->id(keys[i])] = true;
+      }
+      if (strictCheck) {
+        std::vector<bool> fl(flag.size(), false);
+        const typename Parent::Notifier* notifier = Parent::getNotifier();
+        Item it;
+        for (notifier->first(it); it != INVALID; notifier->next(it)) {
+          int id = Parent::getNotifier()->id(it);
+          fl[id] = true;
+        }
+        LEMON_ASSERT(fl == flag, MapError());
+      }
+    }
+
+    /// \brief Erase a key from the map.
+    ///
+    /// Erase a key from the map. It called by the observer notifier
+    /// and it overrides the erase() member function of the observer base.     
+    virtual void erase(const Key& key) {
+      if (strictCheck) {
+        std::vector<bool> fl(flag.size(), false);
+        const typename Parent::Notifier* notifier = Parent::getNotifier();
+        Item it;
+        for (notifier->first(it); it != INVALID; notifier->next(it)) {
+          int id = Parent::getNotifier()->id(it);
+          fl[id] = true;
+        }
+        LEMON_ASSERT(fl == flag, MapError());
+      }
+      container[Parent::getNotifier()->id(key)] = Value();
+      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
+      flag[Parent::getNotifier()->id(key)] = false;
+    }
+
+    /// \brief Erase more keys from the map.
+    ///
+    /// Erase more keys from the map. It called by the observer notifier
+    /// and it overrides the erase() member function of the observer base.     
+    virtual void erase(const std::vector<Key>& keys) {
+      if (strictCheck) {
+        std::vector<bool> fl(flag.size(), false);
+        const typename Parent::Notifier* notifier = Parent::getNotifier();
+        Item it;
+        for (notifier->first(it); it != INVALID; notifier->next(it)) {
+          int id = Parent::getNotifier()->id(it);
+          fl[id] = true;
+        }
+        LEMON_ASSERT(fl == flag, MapError());
+      }
+      for (int i = 0; i < (int)keys.size(); ++i) {
+	container[Parent::getNotifier()->id(keys[i])] = Value();
+        LEMON_ASSERT(flag[Parent::getNotifier()->id(keys[i])], MapError());
+        flag[Parent::getNotifier()->id(keys[i])] = false;
+      }
+    }
+    
+    /// \brief Buildes the map.
+    ///	
+    /// It buildes the map. It called by the observer notifier
+    /// and it overrides the build() member function of the observer base.
+    virtual void build() { 
+      if (strictCheck) {
+        for (int i = 0; i < (int)flag.size(); ++i) {
+          LEMON_ASSERT(flag[i], MapError());
+        }
+      }
+      int size = Parent::getNotifier()->maxId() + 1;
+      container.reserve(size);
+      container.resize(size);
+      flag.reserve(size);
+      flag.resize(size, false);
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        int id = Parent::getNotifier()->id(it);
+        LEMON_ASSERT(!flag[id], MapError());
+        flag[id] = true;
+      }
+    }
+
+    /// \brief Clear the map.
+    ///
+    /// It erase all items from the map. It called by the observer notifier
+    /// and it overrides the clear() member function of the observer base.     
+    virtual void clear() { 
+      const typename Parent::Notifier* notifier = Parent::getNotifier();
+      Item it;
+      for (notifier->first(it); it != INVALID; notifier->next(it)) {
+        int id = Parent::getNotifier()->id(it);
+        LEMON_ASSERT(flag[id], MapError());
+        flag[id] = false;
+      }
+      if (strictCheck) {
+        for (int i = 0; i < (int)flag.size(); ++i) {
+          LEMON_ASSERT(!flag[i], MapError());
+        }
+      }
+      container.clear();
+      flag.clear();
+    }
+    
+  private:
+		
+    Container container;
+    Flag flag;
+
+  };
+
+}
+
+#endif

Modified: hugo/trunk/lemon/bits/default_map.h
==============================================================================
--- hugo/trunk/lemon/bits/default_map.h	(original)
+++ hugo/trunk/lemon/bits/default_map.h	Wed Sep  6 12:19:57 2006
@@ -22,6 +22,7 @@
 
 #include <lemon/bits/array_map.h>
 #include <lemon/bits/vector_map.h>
+#include <lemon/bits/debug_map.h>
 
 ///\ingroup graphbits
 ///\file
@@ -37,15 +38,6 @@
     typedef ArrayMap<_Graph, _Item, _Value> Map;
   };
 
-#else
-
-  template <typename _Graph, typename _Item, typename _Value>
-  struct DefaultMapSelector {
-    typedef VectorMap<_Graph, _Item, _Value> Map;
-  };
-
-#endif
-
   // bool
   template <typename _Graph, typename _Item>
   struct DefaultMapSelector<_Graph, _Item, bool> {
@@ -148,6 +140,15 @@
     typedef VectorMap<_Graph, _Item, _Ptr*> Map;
   };
 
+#else 
+
+  template <typename _Graph, typename _Item, typename _Value>
+  struct DefaultMapSelector {
+    typedef DebugMap<_Graph, _Item, _Value> Map;
+  };
+
+#endif  
+
   /// \e
   template <typename _Graph, typename _Item, typename _Value>
   class DefaultMap 

Modified: hugo/trunk/lemon/bits/vector_map.h
==============================================================================
--- hugo/trunk/lemon/bits/vector_map.h	(original)
+++ hugo/trunk/lemon/bits/vector_map.h	Wed Sep  6 12:19:57 2006
@@ -42,9 +42,7 @@
   ///
   /// The VectorMap template class is graph map structure what
   /// automatically updates the map when a key is added to or erased from
-  /// the map. This map factory uses the allocators to implement 
-  /// the container functionality. This map factory
-  /// uses the std::vector to implement the container function.
+  /// the map. This map type uses the std::vector to store the values.
   ///
   /// \param Notifier The AlterationNotifier that will notify this map.
   /// \param Item The item type of the graph items.



More information about the Lemon-commits mailing list