raw_hash_set.cc 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright 2018 The Abseil Authors.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/container/internal/raw_hash_set.h"
  15. #include <atomic>
  16. #include <cstddef>
  17. #include "absl/base/config.h"
  18. namespace absl {
  19. ABSL_NAMESPACE_BEGIN
  20. namespace container_internal {
  21. alignas(16) ABSL_CONST_INIT ABSL_DLL const ctrl_t kEmptyGroup[16] = {
  22. ctrl_t::kSentinel, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
  23. ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
  24. ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
  25. ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty};
  26. constexpr size_t Group::kWidth;
  27. // Returns "random" seed.
  28. inline size_t RandomSeed() {
  29. #ifdef ABSL_HAVE_THREAD_LOCAL
  30. static thread_local size_t counter = 0;
  31. size_t value = ++counter;
  32. #else // ABSL_HAVE_THREAD_LOCAL
  33. static std::atomic<size_t> counter(0);
  34. size_t value = counter.fetch_add(1, std::memory_order_relaxed);
  35. #endif // ABSL_HAVE_THREAD_LOCAL
  36. return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
  37. }
  38. bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl) {
  39. // To avoid problems with weak hashes and single bit tests, we use % 13.
  40. // TODO(kfm,sbenza): revisit after we do unconditional mixing
  41. return (H1(hash, ctrl) ^ RandomSeed()) % 13 > 6;
  42. }
  43. void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
  44. assert(ctrl[capacity] == ctrl_t::kSentinel);
  45. assert(IsValidCapacity(capacity));
  46. for (ctrl_t* pos = ctrl; pos < ctrl + capacity; pos += Group::kWidth) {
  47. Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
  48. }
  49. // Copy the cloned ctrl bytes.
  50. std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());
  51. ctrl[capacity] = ctrl_t::kSentinel;
  52. }
  53. // Extern template instantiotion for inline function.
  54. template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
  55. } // namespace container_internal
  56. ABSL_NAMESPACE_END
  57. } // namespace absl