# debug_map_base.hpp

Go to the documentation of this file.

    00001 // -*- C++ -*-
    00002
    00003 // Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the terms
    00007 // of the GNU General Public License as published by the Free Software
    00008 // Foundation; either version 2, or (at your option) any later
    00009 // version.
    00010
    00011 // This library is distributed in the hope that it will be useful, but
    00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014 // General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License
    00017 // along with this library; see the file COPYING.  If not, write to
    00018 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
    00019 // MA 02111-1307, USA.
    00020
    00021 // As a special exception, you may use this file as part of a free
    00022 // software library without restriction.  Specifically, if other files
    00023 // instantiate templates or use macros or inline functions from this
    00024 // file, or you compile this file and link it with other files to
    00025 // produce an executable, this file does not by itself cause the
    00026 // resulting executable to be covered by the GNU General Public
    00027 // License.  This exception does not however invalidate any other
    00028 // reasons why the executable file might be covered by the GNU General
    00029 // Public License.
    00030
    00031 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
    00032
    00033 // Permission to use, copy, modify, sell, and distribute this software
    00034 // is hereby granted without fee, provided that the above copyright
    00035 // notice appears in all copies, and that both that copyright notice
    00036 // and this permission notice appear in supporting documentation. None
    00037 // of the above authors, nor IBM Haifa Research Laboratories, make any
    00038 // representation about the suitability of this software for any
    00039 // purpose. It is provided "as is" without express or implied
    00040 // warranty.
    00041
    00042 /**
    00043  * @file debug_map_base.hpp
    00044  * Contains a debug-mode base for all maps.
    00045  */
    00046
    00047 #ifndef PB_DS_DEBUG_MAP_BASE_HPP
    00048 #define PB_DS_DEBUG_MAP_BASE_HPP
    00049
    00050 #ifdef _GLIBCXX_DEBUG
    00051
    00052 #include <list>
    00053 #include <utility>
    00054 #include <cstdlib>
    00055 #include <ext/throw_allocator.h>
    00056 #include <debug/debug.h>
    00057
    00058 namespace __gnu_pbds
    00059 {
    00060   namespace detail
    00061   {
    00062     // Need std::pair ostream extractor.
    00063     template<typename _CharT, typename _Traits, typename _Tp1, typename _Tp2>
    00064     inline std::basic_ostream<_CharT, _Traits>&
    00065     operator<<(std::basic_ostream<_CharT, _Traits>& __out,
    00066            const std::pair<_Tp1, _Tp2>& p)
    00067     { return (__out << '(' << p.first << ',' << p.second << ')'); }
    00068
    00069 #define PB_DS_CLASS_T_DEC \
    00070     template<typename Key, class Eq_Fn, typename Const_Key_Reference>
    00071
    00072 #define PB_DS_CLASS_C_DEC \
    00073     debug_map_base<Key, Eq_Fn, Const_Key_Reference>
    00074
    00075     template<typename Key, class Eq_Fn, typename Const_Key_Reference>
    00076     class debug_map_base
    00077     {
    00078     private:
    00079       typedef typename std::allocator< Key> key_allocator;
    00080
    00081       typedef typename key_allocator::size_type size_type;
    00082
    00083       typedef Const_Key_Reference const_key_reference;
    00084
    00085     protected:
    00086       debug_map_base();
    00087
    00088       debug_map_base(const PB_DS_CLASS_C_DEC& other);
    00089
    00090       ~debug_map_base();
    00091
    00092       inline void
    00093       insert_new(const_key_reference r_key);
    00094
    00095       inline void
    00096       erase_existing(const_key_reference r_key);
    00097
    00098       void
    00099       clear();
    00100
    00101       inline void
    00102       check_key_exists(const_key_reference r_key) const;
    00103
    00104       inline void
    00105       check_key_does_not_exist(const_key_reference r_key) const;
    00106
    00107       inline void
    00108       check_size(size_type size) const;
    00109
    00110       void
    00111       swap(PB_DS_CLASS_C_DEC& other);
    00112
    00113       template<typename Cmp_Fn>
    00114       void
    00115       split(const_key_reference, Cmp_Fn, PB_DS_CLASS_C_DEC&);
    00116
    00117       void
    00118       join(PB_DS_CLASS_C_DEC& other);
    00119
    00120     private:
    00121       typedef std::list< Key>           key_set;
    00122       typedef typename key_set::iterator    key_set_iterator;
    00123       typedef typename key_set::const_iterator  const_key_set_iterator;
    00124
    00125 #ifdef _GLIBCXX_DEBUG
    00126       void
    00127       assert_valid() const;
    00128 #endif
    00129
    00130       const_key_set_iterator
    00131       find(const_key_reference r_key) const;
    00132
    00133       key_set_iterator
    00134       find(const_key_reference r_key);
    00135
    00136       key_set   m_key_set;
    00137       Eq_Fn     m_eq;
    00138     };
    00139
    00140     PB_DS_CLASS_T_DEC
    00141     PB_DS_CLASS_C_DEC::
    00142     debug_map_base()
    00143     { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
    00144
    00145     PB_DS_CLASS_T_DEC
    00146     PB_DS_CLASS_C_DEC::
    00147     debug_map_base(const PB_DS_CLASS_C_DEC& other) : m_key_set(other.m_key_set)
    00148     { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
    00149
    00150     PB_DS_CLASS_T_DEC
    00151     PB_DS_CLASS_C_DEC::
    00152     ~debug_map_base()
    00153     { _GLIBCXX_DEBUG_ONLY(assert_valid();) }
    00154
    00155     PB_DS_CLASS_T_DEC
    00156     inline void
    00157     PB_DS_CLASS_C_DEC::
    00158     insert_new(const_key_reference r_key)
    00159     {
    00160       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00161       __gnu_cxx::throw_allocator<char> alloc;
    00162       const double orig_throw_prob = alloc.get_throw_prob();
    00163       alloc.set_throw_prob(0);
    00164       if (find(r_key) != m_key_set.end())
    00165     {
    00166       std::cerr << "insert_new" << r_key << std::endl;
    00167       std::abort();
    00168     }
    00169
    00170       try
    00171     {
    00172       m_key_set.push_back(r_key);
    00173     }
    00174       catch(...)
    00175     {
    00176       std::cerr << "insert_new" << r_key << std::endl;
    00177       std::abort();
    00178     }
    00179       alloc.set_throw_prob(orig_throw_prob);
    00180       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00181     }
    00182
    00183     PB_DS_CLASS_T_DEC
    00184     inline void
    00185     PB_DS_CLASS_C_DEC::
    00186     erase_existing(const_key_reference r_key)
    00187     {
    00188       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00189       key_set_iterator it = find(r_key);
    00190       if (it == m_key_set.end())
    00191     {
    00192       std::cerr << "erase_existing" << r_key << std::endl;
    00193       std::abort();
    00194     }
    00195       m_key_set.erase(it);
    00196       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00197     }
    00198
    00199     PB_DS_CLASS_T_DEC
    00200     void
    00201     PB_DS_CLASS_C_DEC::
    00202     clear()
    00203     {
    00204       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00205       m_key_set.clear();
    00206       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00207     }
    00208
    00209     PB_DS_CLASS_T_DEC
    00210     inline void
    00211     PB_DS_CLASS_C_DEC::
    00212     check_key_exists(const_key_reference r_key) const
    00213     {
    00214       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00215       if (find(r_key) == m_key_set.end())
    00216         {
    00217           std::cerr << "check_key_exists" << r_key << std::endl;
    00218           std::abort();
    00219         }
    00220       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00221     }
    00222
    00223     PB_DS_CLASS_T_DEC
    00224     inline void
    00225     PB_DS_CLASS_C_DEC::
    00226     check_key_does_not_exist(const_key_reference r_key) const
    00227     {
    00228       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00229       if (find(r_key) != m_key_set.end())
    00230         {
    00231       using std::cerr;
    00232       using std::endl;
    00233       cerr << "check_key_does_not_exist" << r_key << endl;
    00234           std::abort();
    00235         }
    00236     }
    00237
    00238     PB_DS_CLASS_T_DEC
    00239     inline void
    00240     PB_DS_CLASS_C_DEC::
    00241     check_size(size_type size) const
    00242     {
    00243       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00244       const size_type key_set_size = m_key_set.size();
    00245       if (size != key_set_size)
    00246     {
    00247       std::cerr << "check_size " << size
    00248             << " " << key_set_size << std::endl;
    00249       std::abort();
    00250     }
    00251       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00252      }
    00253
    00254     PB_DS_CLASS_T_DEC
    00255     void
    00256     PB_DS_CLASS_C_DEC::
    00257     swap(PB_DS_CLASS_C_DEC& other)
    00258     {
    00259       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00260       m_key_set.swap(other.m_key_set);
    00261       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00262     }
    00263
    00264     PB_DS_CLASS_T_DEC
    00265     typename PB_DS_CLASS_C_DEC::const_key_set_iterator
    00266     PB_DS_CLASS_C_DEC::
    00267     find(const_key_reference r_key) const
    00268     {
    00269       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00270       typedef const_key_set_iterator iterator_type;
    00271       for (iterator_type it = m_key_set.begin(); it != m_key_set.end(); ++it)
    00272     if (m_eq(*it, r_key))
    00273           return it;
    00274       return m_key_set.end();
    00275     }
    00276
    00277     PB_DS_CLASS_T_DEC
    00278     typename PB_DS_CLASS_C_DEC::key_set_iterator
    00279     PB_DS_CLASS_C_DEC::
    00280     find(const_key_reference r_key)
    00281     {
    00282       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00283       key_set_iterator it = m_key_set.begin();
    00284       while (it != m_key_set.end())
    00285     {
    00286       if (m_eq(*it, r_key))
    00287             return it;
    00288       ++it;
    00289     }
    00290       return it;
    00291       _GLIBCXX_DEBUG_ONLY(assert_valid();)
    00292      }
    00293
    00294 #ifdef _GLIBCXX_DEBUG
    00295     PB_DS_CLASS_T_DEC
    00296     void
    00297     PB_DS_CLASS_C_DEC::
    00298     assert_valid() const
    00299     {
    00300       const_key_set_iterator prime_it = m_key_set.begin();
    00301       while (prime_it != m_key_set.end())
    00302     {
    00303       const_key_set_iterator sec_it = prime_it;
    00304       ++sec_it;
    00305       while (sec_it != m_key_set.end())
    00306         {
    00307           _GLIBCXX_DEBUG_ASSERT(!m_eq(*sec_it, *prime_it));
    00308           _GLIBCXX_DEBUG_ASSERT(!m_eq(*prime_it, *sec_it));
    00309           ++sec_it;
    00310         }
    00311       ++prime_it;
    00312     }
    00313     }
    00314 #endif
    00315
    00316     PB_DS_CLASS_T_DEC
    00317     template<typename Cmp_Fn>
    00318     void
    00319     PB_DS_CLASS_C_DEC::
    00320     split(const_key_reference r_key, Cmp_Fn cmp_fn, PB_DS_CLASS_C_DEC& other)
    00321     {
    00322       __gnu_cxx::throw_allocator<char> alloc;
    00323       const double orig_throw_prob = alloc.get_throw_prob();
    00324       alloc.set_throw_prob(0);
    00325       other.clear();
    00326       key_set_iterator it = m_key_set.begin();
    00327       while (it != m_key_set.end())
    00328         if (cmp_fn(r_key, * it))
    00329       {
    00330             other.insert_new(*it);
    00331             it = m_key_set.erase(it);
    00332       }
    00333         else
    00334       ++it;
    00335       alloc.set_throw_prob(orig_throw_prob);
    00336     }
    00337
    00338     PB_DS_CLASS_T_DEC
    00339     void
    00340     PB_DS_CLASS_C_DEC::
    00341     join(PB_DS_CLASS_C_DEC& other)
    00342     {
    00343       __gnu_cxx::throw_allocator<char> alloc;
    00344       const double orig_throw_prob = alloc.get_throw_prob();
    00345       alloc.set_throw_prob(0);
    00346       key_set_iterator it = other.m_key_set.begin();
    00347       while (it != other.m_key_set.end())
    00348     {
    00349       insert_new(*it);
    00350       it = other.m_key_set.erase(it);
    00351     }
    00352       _GLIBCXX_DEBUG_ASSERT(other.m_key_set.empty());
    00353       alloc.set_throw_prob(orig_throw_prob);
    00354     }
    00355
    00356 #undef PB_DS_CLASS_T_DEC
    00357 #undef PB_DS_CLASS_C_DEC
    00358
    00359 } // namespace detail
    00360 } // namespace __gnu_pbds
    00361
    00362 #endif
    00363
    00364 #endif
    00365