Home | History | Annotate | Line # | Download | only in gcc
hash-set.h revision 1.4
      1 /* A type-safe hash set.
      2    Copyright (C) 2014-2018 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify it under
      7 the terms of the GNU General Public License as published by the Free
      8 Software Foundation; either version 3, or (at your option) any later
      9 version.
     10 
     11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14 for more details.
     15 
     16 You should have received a copy of the GNU General Public License
     17 along with GCC; see the file COPYING3.  If not see
     18 <http://www.gnu.org/licenses/>.  */
     19 
     20 
     21 #ifndef hash_set_h
     22 #define hash_set_h
     23 
     24 template<typename KeyId, typename Traits = default_hash_traits<KeyId> >
     25 class hash_set
     26 {
     27 public:
     28   typedef typename Traits::value_type Key;
     29   explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO)
     30     : m_table (n, ggc, GATHER_STATISTICS, HASH_SET_ORIGIN PASS_MEM_STAT) {}
     31 
     32   /* Create a hash_set in gc memory with space for at least n elements.  */
     33 
     34   static hash_set *
     35     create_ggc (size_t n)
     36       {
     37 	hash_set *set = ggc_alloc<hash_set> ();
     38 	new (set) hash_set (n, true);
     39 	return set;
     40       }
     41 
     42   /* If key k isn't already in the map add it to the map, and
     43      return false.  Otherwise return true.  */
     44 
     45   bool add (const Key &k)
     46     {
     47       Key *e = m_table.find_slot_with_hash (k, Traits::hash (k), INSERT);
     48       bool existed = !Traits::is_empty (*e);
     49       if (!existed)
     50 	*e = k;
     51 
     52       return existed;
     53     }
     54 
     55   /* if the passed in key is in the map return its value otherwise NULL.  */
     56 
     57   bool contains (const Key &k)
     58     {
     59       Key &e = m_table.find_with_hash (k, Traits::hash (k));
     60       return !Traits::is_empty (e);
     61     }
     62 
     63   void remove (const Key &k)
     64     {
     65       m_table.remove_elt_with_hash (k, Traits::hash (k));
     66     }
     67 
     68   /* Call the call back on each pair of key and value with the passed in
     69      arg.  */
     70 
     71   template<typename Arg, bool (*f)(const typename Traits::value_type &, Arg)>
     72   void traverse (Arg a) const
     73     {
     74       for (typename hash_table<Traits>::iterator iter = m_table.begin ();
     75 	   iter != m_table.end (); ++iter)
     76 	f (*iter, a);
     77     }
     78 
     79   /* Return the number of elements in the set.  */
     80 
     81   size_t elements () const { return m_table.elements (); }
     82 
     83   /* Clear the hash table.  */
     84 
     85   void empty () { m_table.empty (); }
     86 
     87   class iterator
     88   {
     89   public:
     90     explicit iterator (const typename hash_table<Traits>::iterator &iter) :
     91       m_iter (iter) {}
     92 
     93     iterator &operator++ ()
     94       {
     95 	++m_iter;
     96 	return *this;
     97       }
     98 
     99     Key
    100     operator* ()
    101       {
    102 	return *m_iter;
    103       }
    104 
    105     bool
    106     operator != (const iterator &other) const
    107       {
    108 	return m_iter != other.m_iter;
    109       }
    110 
    111   private:
    112     typename hash_table<Traits>::iterator m_iter;
    113   };
    114 
    115   /* Standard iterator retrieval methods.  */
    116 
    117   iterator begin () const { return iterator (m_table.begin ()); }
    118   iterator end () const { return iterator (m_table.end ()); }
    119 
    120 
    121 private:
    122 
    123   template<typename T, typename U> friend void gt_ggc_mx (hash_set<T, U> *);
    124   template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *);
    125       template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
    126 
    127   hash_table<Traits> m_table;
    128 };
    129 
    130 /* Generic hash_set<TYPE> debug helper.
    131 
    132    This needs to be instantiated for each hash_set<TYPE> used throughout
    133    the compiler like this:
    134 
    135     DEFINE_DEBUG_HASH_SET (TYPE)
    136 
    137    The reason we have a debug_helper() is because GDB can't
    138    disambiguate a plain call to debug(some_hash), and it must be called
    139    like debug<TYPE>(some_hash).  */
    140 template<typename T>
    141 void
    142 debug_helper (hash_set<T> &ref)
    143 {
    144   for (typename hash_set<T>::iterator it = ref.begin ();
    145        it != ref.end (); ++it)
    146     {
    147       debug_slim (*it);
    148       fputc ('\n', stderr);
    149     }
    150 }
    151 
    152 #define DEFINE_DEBUG_HASH_SET(T) \
    153   template void debug_helper (hash_set<T> &);		\
    154   DEBUG_FUNCTION void					\
    155   debug (hash_set<T> &ref)				\
    156   {							\
    157     debug_helper <T> (ref);				\
    158   }							\
    159   DEBUG_FUNCTION void					\
    160   debug (hash_set<T> *ptr)				\
    161   {							\
    162     if (ptr)						\
    163       debug (*ptr);					\
    164     else						\
    165       fprintf (stderr, "<nil>\n");			\
    166   }
    167 
    168 /* ggc marking routines.  */
    169 
    170 template<typename K, typename H>
    171 static inline void
    172 gt_ggc_mx (hash_set<K, H> *h)
    173 {
    174   gt_ggc_mx (&h->m_table);
    175 }
    176 
    177 template<typename K, typename H>
    178 static inline void
    179 gt_pch_nx (hash_set<K, H> *h)
    180 {
    181   gt_pch_nx (&h->m_table);
    182 }
    183 
    184 template<typename K, typename H>
    185 static inline void
    186 gt_pch_nx (hash_set<K, H> *h, gt_pointer_operator op, void *cookie)
    187 {
    188   op (&h->m_table.m_entries, cookie);
    189 }
    190 
    191 #endif
    192