Home | History | Annotate | Line # | Download | only in gcc
hash-set.h revision 1.5
      1 /* A type-safe hash set.
      2    Copyright (C) 2014-2019 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, bool Lazy = false,
     25 	 typename Traits = default_hash_traits<KeyId> >
     26 class hash_set
     27 {
     28 public:
     29   typedef typename Traits::value_type Key;
     30   explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO)
     31     : m_table (n, ggc, GATHER_STATISTICS, HASH_SET_ORIGIN PASS_MEM_STAT) {}
     32 
     33   /* Create a hash_set in gc memory with space for at least n elements.  */
     34 
     35   static hash_set *
     36   create_ggc (size_t n)
     37     {
     38       hash_set *set = ggc_alloc<hash_set> ();
     39       new (set) hash_set (n, true);
     40       return set;
     41     }
     42 
     43   /* If key k isn't already in the map add it to the map, and
     44      return false.  Otherwise return true.  */
     45 
     46   bool add (const Key &k)
     47     {
     48       Key *e = m_table.find_slot_with_hash (k, Traits::hash (k), INSERT);
     49       bool existed = !Traits::is_empty (*e);
     50       if (!existed)
     51 	*e = k;
     52 
     53       return existed;
     54     }
     55 
     56   /* if the passed in key is in the map return its value otherwise NULL.  */
     57 
     58   bool contains (const Key &k)
     59     {
     60       if (Lazy)
     61 	return (m_table.find_slot_with_hash (k, Traits::hash (k), NO_INSERT)
     62 		!= NULL);
     63       Key &e = m_table.find_with_hash (k, Traits::hash (k));
     64       return !Traits::is_empty (e);
     65     }
     66 
     67   void remove (const Key &k)
     68     {
     69       m_table.remove_elt_with_hash (k, Traits::hash (k));
     70     }
     71 
     72   /* Call the call back on each pair of key and value with the passed in
     73      arg.  */
     74 
     75   template<typename Arg, bool (*f)(const typename Traits::value_type &, Arg)>
     76   void traverse (Arg a) const
     77     {
     78       for (typename hash_table<Traits, Lazy>::iterator iter = m_table.begin ();
     79 	   iter != m_table.end (); ++iter)
     80 	f (*iter, a);
     81     }
     82 
     83   /* Return the number of elements in the set.  */
     84 
     85   size_t elements () const { return m_table.elements (); }
     86 
     87   /* Clear the hash table.  */
     88 
     89   void empty () { m_table.empty (); }
     90 
     91   class iterator
     92   {
     93   public:
     94     explicit iterator (const typename hash_table<Traits,
     95 						 Lazy>::iterator &iter) :
     96       m_iter (iter) {}
     97 
     98     iterator &operator++ ()
     99       {
    100 	++m_iter;
    101 	return *this;
    102       }
    103 
    104     Key
    105     operator* ()
    106       {
    107 	return *m_iter;
    108       }
    109 
    110     bool
    111     operator != (const iterator &other) const
    112       {
    113 	return m_iter != other.m_iter;
    114       }
    115 
    116   private:
    117     typename hash_table<Traits, Lazy>::iterator m_iter;
    118   };
    119 
    120   /* Standard iterator retrieval methods.  */
    121 
    122   iterator begin () const { return iterator (m_table.begin ()); }
    123   iterator end () const { return iterator (m_table.end ()); }
    124 
    125 
    126 private:
    127 
    128   template<typename T, typename U>
    129   friend void gt_ggc_mx (hash_set<T, false, U> *);
    130   template<typename T, typename U>
    131   friend void gt_pch_nx (hash_set<T, false, U> *);
    132   template<typename T, typename U>
    133   friend void gt_pch_nx (hash_set<T, false, U> *, gt_pointer_operator, void *);
    134 
    135   hash_table<Traits, Lazy> m_table;
    136 };
    137 
    138 /* Generic hash_set<TYPE> debug helper.
    139 
    140    This needs to be instantiated for each hash_set<TYPE> used throughout
    141    the compiler like this:
    142 
    143     DEFINE_DEBUG_HASH_SET (TYPE)
    144 
    145    The reason we have a debug_helper() is because GDB can't
    146    disambiguate a plain call to debug(some_hash), and it must be called
    147    like debug<TYPE>(some_hash).  */
    148 template<typename T>
    149 void
    150 debug_helper (hash_set<T> &ref)
    151 {
    152   for (typename hash_set<T>::iterator it = ref.begin ();
    153        it != ref.end (); ++it)
    154     {
    155       debug_slim (*it);
    156       fputc ('\n', stderr);
    157     }
    158 }
    159 
    160 #define DEFINE_DEBUG_HASH_SET(T) \
    161   template void debug_helper (hash_set<T> &);		\
    162   DEBUG_FUNCTION void					\
    163   debug (hash_set<T> &ref)				\
    164   {							\
    165     debug_helper <T> (ref);				\
    166   }							\
    167   DEBUG_FUNCTION void					\
    168   debug (hash_set<T> *ptr)				\
    169   {							\
    170     if (ptr)						\
    171       debug (*ptr);					\
    172     else						\
    173       fprintf (stderr, "<nil>\n");			\
    174   }
    175 
    176 /* ggc marking routines.  */
    177 
    178 template<typename K, typename H>
    179 static inline void
    180 gt_ggc_mx (hash_set<K, false, H> *h)
    181 {
    182   gt_ggc_mx (&h->m_table);
    183 }
    184 
    185 template<typename K, typename H>
    186 static inline void
    187 gt_pch_nx (hash_set<K, false, H> *h)
    188 {
    189   gt_pch_nx (&h->m_table);
    190 }
    191 
    192 template<typename K, typename H>
    193 static inline void
    194 gt_pch_nx (hash_set<K, false, H> *h, gt_pointer_operator op, void *cookie)
    195 {
    196   op (&h->m_table.m_entries, cookie);
    197 }
    198 
    199 #endif
    200