hash_table.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* Definitions for the hash table template type.
  2. This file is part of xrcu.
  3. xrcu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #include "hash_table.hpp"
  14. #include <new>
  15. #include <thread>
  16. #include <cstdint>
  17. namespace xrcu
  18. {
  19. namespace detail
  20. {
  21. inline ht_vector* ht_vector_make (size_t n)
  22. {
  23. void *p = ::operator new (sizeof (ht_vector) + n * sizeof (uintptr_t));
  24. return (new (p) ht_vector ((uintptr_t *)((char *)p + sizeof (ht_vector))));
  25. }
  26. void ht_vector::safe_destroy ()
  27. {
  28. ::operator delete (this);
  29. }
  30. static const size_t PRIMES[] =
  31. {
  32. 0xb, 0x25, 0x71, 0x15b, 0x419, 0xc4d, 0x24f5, 0x6ee3, 0x14cb3, 0x3e61d,
  33. 0xbb259, 0x23170f, 0x694531, 0x13bcf95, 0x3b36ec3, 0xb1a4c4b, 0x214ee4e3,
  34. 0x63ecaead
  35. #if SIZE_MAX > 0xffffffffu
  36. , 0x12bc60c09ull, 0x38352241dull, 0xa89f66c5bull, 0x1f9de34513ull,
  37. 0x5ed9a9cf3bull, 0x11c8cfd6db5ull, 0x355a6f84921ull, 0xa00f4e8db65ull,
  38. 0x1e02deba9233ull, 0x5a089c2fb69bull, 0x10e19d48f23d3ull, 0x32a4d7dad6b7dull,
  39. 0x97ee879084279ull, 0x1c7cb96b18c76dull, 0x55762c414a564bull,
  40. 0x1006284c3df02e3ull, 0x301278e4b9d08abull, 0x90376aae2d71a05ull,
  41. 0x1b0a6400a8854e11ull, 0x511f2c01f98fea35ull
  42. #endif
  43. };
  44. size_t find_hsize (size_t size, float mvr, size_t& pidx)
  45. {
  46. intptr_t i1 = 0, i2 = sizeof (PRIMES) / sizeof (PRIMES[0]);
  47. while (i1 < i2)
  48. {
  49. intptr_t step = (i1 + i2) >> 1;
  50. if (PRIMES[step] < size)
  51. i1 = step + 1;
  52. else
  53. i2 = step;
  54. }
  55. pidx = i1;
  56. return ((size_t)(PRIMES[i1] * mvr));
  57. }
  58. ht_vector* make_htvec (size_t pidx, uintptr_t key, uintptr_t val)
  59. {
  60. size_t entries = PRIMES[pidx], tsize = table_idx (entries);
  61. #ifdef XRCU_HAVE_XATOMIC_DCAS
  62. auto ret = ht_vector_make (tsize + 1);
  63. // Ensure correct alignment for double-width CAS.
  64. if ((uintptr_t)ret->data % (2 * sizeof (uintptr_t)) != 0)
  65. ++ret->data;
  66. #else
  67. auto ret = ht_vector_make (tsize);
  68. #endif
  69. for (size_t i = 0; i < tsize; i += 2)
  70. ret->data[i] = key, ret->data[i + 1] = val;
  71. ret->entries = entries;
  72. ret->pidx = pidx;
  73. return (ret);
  74. }
  75. } // namespace detail
  76. } // namespace xrcu