hash-set.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /* A type-safe hash set.
  2. Copyright (C) 2014-2015 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. #include "hash-table.h"
  18. /* implement default behavior for traits when types allow it. */
  19. struct default_hashset_traits
  20. {
  21. /* Hashes the passed in key. */
  22. template<typename T>
  23. static hashval_t
  24. hash (T *p)
  25. {
  26. return uintptr_t(p) >> 3;
  27. }
  28. template<typename T> static hashval_t hash(const T &v) { return v; }
  29. /* Return true if the two keys passed as arguments are equal. */
  30. template<typename T>
  31. static bool
  32. equal (const T &a, const T &b)
  33. {
  34. return a == b;
  35. }
  36. /* Called to dispose of the key before marking the entry as deleted. */
  37. template<typename T> static void remove (T &v) { v.~T (); }
  38. /* Mark the passed in entry as being deleted. */
  39. template<typename T>
  40. static void
  41. mark_deleted (T *&e)
  42. {
  43. e = reinterpret_cast<void *> (1);
  44. }
  45. /* Mark the passed in entry as being empty. */
  46. template<typename T>
  47. static void
  48. mark_empty (T *&e)
  49. {
  50. e = NULL;
  51. }
  52. /* Return true if the passed in entry is marked as deleted. */
  53. template<typename T>
  54. static bool
  55. is_deleted (T *e)
  56. {
  57. return e == reinterpret_cast<void *> (1);
  58. }
  59. /* Return true if the passed in entry is marked as empty. */
  60. template<typename T> static bool is_empty (T *e) { return e == NULL; }
  61. /* ggc walking routine, mark all objects refered to by this one. */
  62. template<typename T>
  63. static void
  64. ggc_mx (T &x)
  65. {
  66. extern void gt_ggc_mx (T &);
  67. gt_ggc_mx (x);
  68. }
  69. /* pch walking routine, note all objects refered to by this element. */
  70. template<typename T>
  71. static void
  72. pch_nx (T &x)
  73. {
  74. extern void gt_pch_nx (T &);
  75. gt_pch_nx (x);
  76. }
  77. };
  78. template<typename Key, typename Traits = default_hashset_traits>
  79. class hash_set
  80. {
  81. struct hash_entry
  82. {
  83. Key m_key;
  84. typedef hash_entry value_type;
  85. typedef Key compare_type;
  86. typedef int store_values_directly;
  87. static hashval_t hash (const hash_entry &e)
  88. {
  89. return Traits::hash (e.m_key);
  90. }
  91. static bool equal (const hash_entry &a, const Key &b)
  92. {
  93. return Traits::equal (a.m_key, b);
  94. }
  95. static void remove (hash_entry &e) { Traits::remove (e.m_key); }
  96. static void
  97. mark_deleted (hash_entry &e)
  98. {
  99. Traits::mark_deleted (e.m_key);
  100. }
  101. static bool is_deleted (const hash_entry &e)
  102. {
  103. return Traits::is_deleted (e.m_key);
  104. }
  105. static void
  106. mark_empty (hash_entry &e)
  107. {
  108. Traits::mark_empty (e.m_key);
  109. }
  110. static bool
  111. is_empty (const hash_entry &e)
  112. {
  113. return Traits::is_empty (e.m_key);
  114. }
  115. static void ggc_mx (hash_entry &e)
  116. {
  117. Traits::ggc_mx (e.m_key);
  118. }
  119. static void pch_nx (hash_entry &e)
  120. {
  121. Traits::pch_nx (e.m_key);
  122. }
  123. static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
  124. {
  125. pch_nx_helper (e.m_key, op, c);
  126. }
  127. private:
  128. template<typename T>
  129. static void
  130. pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
  131. {
  132. gt_pch_nx (&x, op, cookie);
  133. }
  134. template<typename T>
  135. static void
  136. pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
  137. {
  138. op (&x, cookie);
  139. }
  140. };
  141. public:
  142. explicit hash_set (size_t n = 13, bool ggc = false) : m_table (n, ggc) {}
  143. /* Create a hash_set in gc memory with space for at least n elements. */
  144. static hash_set *
  145. create_ggc (size_t n)
  146. {
  147. hash_set *set = ggc_alloc<hash_set> ();
  148. new (set) hash_set (n, true);
  149. return set;
  150. }
  151. /* If key k isn't already in the map add it to the map, and
  152. return false. Otherwise return true. */
  153. bool add (const Key &k)
  154. {
  155. hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
  156. INSERT);
  157. bool existed = !hash_entry::is_empty (*e);
  158. if (!existed)
  159. e->m_key = k;
  160. return existed;
  161. }
  162. /* if the passed in key is in the map return its value otherwise NULL. */
  163. bool contains (const Key &k)
  164. {
  165. hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
  166. return !Traits::is_empty (e.m_key);
  167. }
  168. /* Call the call back on each pair of key and value with the passed in
  169. arg. */
  170. template<typename Arg, bool (*f)(const Key &, Arg)>
  171. void traverse (Arg a) const
  172. {
  173. for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
  174. iter != m_table.end (); ++iter)
  175. f ((*iter).m_key, a);
  176. }
  177. /* Return the number of elements in the set. */
  178. size_t elements () const { return m_table.elements (); }
  179. private:
  180. template<typename T, typename U> friend void gt_ggc_mx (hash_set<T, U> *);
  181. template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *);
  182. template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
  183. hash_table<hash_entry> m_table;
  184. };
  185. /* ggc marking routines. */
  186. template<typename K, typename H>
  187. static inline void
  188. gt_ggc_mx (hash_set<K, H> *h)
  189. {
  190. gt_ggc_mx (&h->m_table);
  191. }
  192. template<typename K, typename H>
  193. static inline void
  194. gt_pch_nx (hash_set<K, H> *h)
  195. {
  196. gt_pch_nx (&h->m_table);
  197. }
  198. template<typename K, typename H>
  199. static inline void
  200. gt_pch_nx (hash_set<K, H> *h, gt_pointer_operator op, void *cookie)
  201. {
  202. op (&h->m_table.m_entries, cookie);
  203. }
  204. #endif