diff options
author | Abseil Team <absl-team@google.com> | 2018-09-27 12:24:54 -0700 |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2018-09-27 15:28:12 -0400 |
commit | 48cd2c3f351ff188bc85684b84a91b6e6d17d896 (patch) | |
tree | 6f92b0cbb0f8282b7df1cd567cb66406fbbb6f80 /absl/container/internal/hash_policy_testing.h | |
parent | e291c279e458761e77a69b09b129d3d1e81f1e80 (diff) |
Export of internal Abseil changes.
--
4eacae3ff1b14b1d309e8092185bc10e8a6203cf by Derek Mauro <dmauro@google.com>:
Release SwissTable - a fast, efficient, cache-friendly hash table.
https://www.youtube.com/watch?v=ncHmEUmJZf4
PiperOrigin-RevId: 214816527
--
df8c3dfab3cfb2f4365909a84d0683b193cfbb11 by Derek Mauro <dmauro@google.com>:
Internal change
PiperOrigin-RevId: 214785288
--
1eabd5266bbcebc33eecc91e5309b751856a75c8 by Abseil Team <absl-team@google.com>:
Internal change
PiperOrigin-RevId: 214722931
--
2ebbfac950f83146b46253038e7dd7dcde9f2951 by Derek Mauro <dmauro@google.com>:
Internal change
PiperOrigin-RevId: 214701684
GitOrigin-RevId: 4eacae3ff1b14b1d309e8092185bc10e8a6203cf
Change-Id: I9ba64e395b22ad7863213d157b8019b082adc19d
Diffstat (limited to 'absl/container/internal/hash_policy_testing.h')
-rw-r--r-- | absl/container/internal/hash_policy_testing.h | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h new file mode 100644 index 00000000..ffc76ead --- /dev/null +++ b/absl/container/internal/hash_policy_testing.h @@ -0,0 +1,178 @@ +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Utilities to help tests verify that hash tables properly handle stateful +// allocators and hash functions. + +#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ +#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ + +#include <cstdlib> +#include <limits> +#include <memory> +#include <ostream> +#include <type_traits> +#include <utility> +#include <vector> + +#include "absl/hash/hash.h" +#include "absl/strings/string_view.h" + +namespace absl { +namespace container_internal { +namespace hash_testing_internal { + +template <class Derived> +struct WithId { + WithId() : id_(next_id<Derived>()) {} + WithId(const WithId& that) : id_(that.id_) {} + WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; } + WithId& operator=(const WithId& that) { + id_ = that.id_; + return *this; + } + WithId& operator=(WithId&& that) { + id_ = that.id_; + that.id_ = 0; + return *this; + } + + size_t id() const { return id_; } + + friend bool operator==(const WithId& a, const WithId& b) { + return a.id_ == b.id_; + } + friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); } + + protected: + explicit WithId(size_t id) : id_(id) {} + + private: + size_t id_; + + template <class T> + static size_t next_id() { + // 0 is reserved for moved from state. + static size_t gId = 1; + return gId++; + } +}; + +} // namespace hash_testing_internal + +struct NonStandardLayout { + NonStandardLayout() {} + explicit NonStandardLayout(std::string s) : value(std::move(s)) {} + virtual ~NonStandardLayout() {} + + friend bool operator==(const NonStandardLayout& a, + const NonStandardLayout& b) { + return a.value == b.value; + } + friend bool operator!=(const NonStandardLayout& a, + const NonStandardLayout& b) { + return a.value != b.value; + } + + template <typename H> + friend H AbslHashValue(H h, const NonStandardLayout& v) { + return H::combine(std::move(h), v.value); + } + + std::string value; +}; + +struct StatefulTestingHash + : absl::container_internal::hash_testing_internal::WithId< + StatefulTestingHash> { + template <class T> + size_t operator()(const T& t) const { + return absl::Hash<T>{}(t); + } +}; + +struct StatefulTestingEqual + : absl::container_internal::hash_testing_internal::WithId< + StatefulTestingEqual> { + template <class T, class U> + bool operator()(const T& t, const U& u) const { + return t == u; + } +}; + +// It is expected that Alloc() == Alloc() for all allocators so we cannot use +// WithId base. We need to explicitly assign ids. +template <class T = int> +struct Alloc : std::allocator<T> { + using propagate_on_container_swap = std::true_type; + + // Using old paradigm for this to ensure compatibility. + explicit Alloc(size_t id = 0) : id_(id) {} + + Alloc(const Alloc&) = default; + Alloc& operator=(const Alloc&) = default; + + template <class U> + Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {} + + template <class U> + struct rebind { + using other = Alloc<U>; + }; + + size_t id() const { return id_; } + + friend bool operator==(const Alloc& a, const Alloc& b) { + return a.id_ == b.id_; + } + friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); } + + private: + size_t id_ = std::numeric_limits<size_t>::max(); +}; + +template <class Map> +auto items(const Map& m) -> std::vector< + std::pair<typename Map::key_type, typename Map::mapped_type>> { + using std::get; + std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res; + res.reserve(m.size()); + for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v)); + return res; +} + +template <class Set> +auto keys(const Set& s) + -> std::vector<typename std::decay<typename Set::key_type>::type> { + std::vector<typename std::decay<typename Set::key_type>::type> res; + res.reserve(s.size()); + for (const auto& v : s) res.emplace_back(v); + return res; +} + +} // namespace container_internal +} // namespace absl + +// ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions +// where the unordered containers are missing certain constructors that +// take allocator arguments. This test is defined ad-hoc for the platforms +// we care about (notably Crosstool 17) because libstdcxx's useless +// versioning scheme precludes a more principled solution. +#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 +#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0 +#else +#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1 +#endif + +#endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_ |