您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

213 行
5.5KB

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