mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 08:34:39 +08:00
wip
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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
|
||||
|
||||
https://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.
|
||||
Vendored
+4
-1
@@ -4,7 +4,7 @@ CXX=CL -EHsc -DNDEBUG -Fo$@ -O2
|
||||
|
||||
ABSEIL_LIBS=absl_bad_optional_access.lib absl_bad_variant_access.lib absl_base.lib absl_demangle_internal.lib absl_hash.lib absl_int128.lib absl_internal_bad_any_cast_impl.lib absl_internal_city.lib absl_internal_civil_time.lib absl_internal_debugging_internal.lib absl_internal_graphcycles_internal.lib absl_internal_hashtablez_sampler.lib absl_internal_malloc_internal.lib absl_internal_spinlock_wait.lib absl_internal_strings_internal.lib absl_internal_throw_delegate.lib absl_internal_time_zone.lib absl_optional.lib absl_raw_hash_set.lib absl_stacktrace.lib absl_strings.lib absl_symbolize.lib absl_synchronization.lib absl_time.lib
|
||||
|
||||
PROGS = stl_unordered_map sparsepp abseil_flat abseil_parallel_flat
|
||||
PROGS = stl_unordered_map sparsepp phmap abseil_flat abseil_parallel_flat
|
||||
BUILD_PROGS = $(addprefix build/,$(PROGS))
|
||||
SIZE = 100000000
|
||||
ABSEIL = ../../abseil-cpp
|
||||
@@ -20,6 +20,9 @@ build/stl_unordered_map: bench.cc Makefile
|
||||
build/sparsepp: bench.cc Makefile
|
||||
$(CXX) -DSPARSEPP -I../../sparsepp bench.cc -o $@
|
||||
|
||||
build/phmap: bench.cc Makefile
|
||||
$(CXX) -DPHMAP -I.. bench.cc /MD -o $@
|
||||
|
||||
build/abseil_flat: bench.cc Makefile
|
||||
$(CXX) -DABSEIL_FLAT -I$(ABSEIL) bench.cc /MD -o $@ /link /LIBPATH:$(ABSEIL)/build/lib ${ABSEIL_LIBS}
|
||||
|
||||
|
||||
+8
-3
@@ -13,9 +13,14 @@
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#define MAPNAME absl::flat_hash_map
|
||||
#define EXTRAARGS
|
||||
#elif defined(ABSEIL_PARALLEL_FLAT)
|
||||
#include "absl/container/parallel_flat_hash_map.h"
|
||||
#define MAPNAME absl::parallel_flat_hash_map
|
||||
#elif defined(ABSEIL_PARALLEL_FLAT) || defined(PHMAP)
|
||||
#if defined(ABSEIL_PARALLEL_FLAT)
|
||||
#include "absl/container/parallel_flat_hash_map.h"
|
||||
#define MAPNAME absl::parallel_flat_hash_map
|
||||
#else
|
||||
#include "parallel_hashmap/phmap.h"
|
||||
#define MAPNAME phmap::parallel_flat_hash_map
|
||||
#endif
|
||||
|
||||
//#define MT_SUPPORT 2
|
||||
#if MT_SUPPORT == 1
|
||||
|
||||
Vendored
+3828
File diff suppressed because it is too large
Load Diff
Vendored
+511
@@ -0,0 +1,511 @@
|
||||
#if !defined(phmap_base_h_guard_)
|
||||
#define phmap_base_h_guard_
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
//
|
||||
// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
|
||||
// with modifications.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#include <stddef.h>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "phmap_config.h"
|
||||
|
||||
namespace phmap {
|
||||
|
||||
namespace type_traits_internal {
|
||||
|
||||
template <typename... Ts>
|
||||
struct VoidTImpl {
|
||||
using type = void;
|
||||
};
|
||||
|
||||
// This trick to retrieve a default alignment is necessary for our
|
||||
// implementation of aligned_storage_t to be consistent with any implementation
|
||||
// of std::aligned_storage.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <size_t Len, typename T = std::aligned_storage<Len>>
|
||||
struct default_alignment_of_aligned_storage;
|
||||
|
||||
template <size_t Len, size_t Align>
|
||||
struct default_alignment_of_aligned_storage<Len,
|
||||
std::aligned_storage<Len, Align>> {
|
||||
static constexpr size_t value = Align;
|
||||
};
|
||||
|
||||
// NOTE: The `is_detected` family of templates here differ from the library
|
||||
// fundamentals specification in that for library fundamentals, `Op<Args...>` is
|
||||
// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
|
||||
// substitution, regardless of whether or not the `::value` is accessed. That
|
||||
// is inconsistent with all other standard traits and prevents lazy evaluation
|
||||
// in larger contexts (such as if the `is_detected` check is a trailing argument
|
||||
// of a `conjunction`. This implementation opts to instead be lazy in the same
|
||||
// way that the standard traits are (this "defect" of the detection idiom
|
||||
// specifications has been reported).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template <class Enabler, template <class...> class Op, class... Args>
|
||||
struct is_detected_impl {
|
||||
using type = std::false_type;
|
||||
};
|
||||
|
||||
template <template <class...> class Op, class... Args>
|
||||
struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
|
||||
using type = std::true_type;
|
||||
};
|
||||
|
||||
template <template <class...> class Op, class... Args>
|
||||
struct is_detected : is_detected_impl<void, Op, Args...>::type {};
|
||||
|
||||
template <class Enabler, class To, template <class...> class Op, class... Args>
|
||||
struct is_detected_convertible_impl {
|
||||
using type = std::false_type;
|
||||
};
|
||||
|
||||
template <class To, template <class...> class Op, class... Args>
|
||||
struct is_detected_convertible_impl<
|
||||
typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
|
||||
To, Op, Args...> {
|
||||
using type = std::true_type;
|
||||
};
|
||||
|
||||
template <class To, template <class...> class Op, class... Args>
|
||||
struct is_detected_convertible
|
||||
: is_detected_convertible_impl<void, To, Op, Args...>::type {};
|
||||
|
||||
template <typename T>
|
||||
using IsCopyAssignableImpl =
|
||||
decltype(std::declval<T&>() = std::declval<const T&>());
|
||||
|
||||
template <typename T>
|
||||
using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
|
||||
|
||||
} // namespace type_traits_internal
|
||||
|
||||
template <typename T>
|
||||
struct is_copy_assignable : type_traits_internal::is_detected<
|
||||
type_traits_internal::IsCopyAssignableImpl, T> {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_move_assignable : type_traits_internal::is_detected<
|
||||
type_traits_internal::IsMoveAssignableImpl, T> {
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// void_t()
|
||||
//
|
||||
// Ignores the type of any its arguments and returns `void`. In general, this
|
||||
// metafunction allows you to create a general case that maps to `void` while
|
||||
// allowing specializations that map to specific types.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++17
|
||||
// `std::void_t` metafunction.
|
||||
//
|
||||
// NOTE: `phmap::void_t` does not use the standard-specified implementation so
|
||||
// that it can remain compatible with gcc < 5.1. This can introduce slightly
|
||||
// different behavior, such as when ordering partial specializations.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename... Ts>
|
||||
using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// conjunction
|
||||
//
|
||||
// Performs a compile-time logical AND operation on the passed types (which
|
||||
// must have `::value` members convertible to `bool`. Short-circuits if it
|
||||
// encounters any `false` members (and does not compare the `::value` members
|
||||
// of any remaining arguments).
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++17
|
||||
// `std::conjunction` metafunction.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename... Ts>
|
||||
struct conjunction;
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
struct conjunction<T, Ts...>
|
||||
: std::conditional<T::value, conjunction<Ts...>, T>::type {};
|
||||
|
||||
template <typename T>
|
||||
struct conjunction<T> : T {};
|
||||
|
||||
template <>
|
||||
struct conjunction<> : std::true_type {};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// disjunction
|
||||
//
|
||||
// Performs a compile-time logical OR operation on the passed types (which
|
||||
// must have `::value` members convertible to `bool`. Short-circuits if it
|
||||
// encounters any `true` members (and does not compare the `::value` members
|
||||
// of any remaining arguments).
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++17
|
||||
// `std::disjunction` metafunction.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename... Ts>
|
||||
struct disjunction;
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
struct disjunction<T, Ts...> :
|
||||
std::conditional<T::value, T, disjunction<Ts...>>::type {};
|
||||
|
||||
template <typename T>
|
||||
struct disjunction<T> : T {};
|
||||
|
||||
template <>
|
||||
struct disjunction<> : std::false_type {};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// negation
|
||||
//
|
||||
// Performs a compile-time logical NOT operation on the passed type (which
|
||||
// must have `::value` members convertible to `bool`.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++17
|
||||
// `std::negation` metafunction.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct negation : std::integral_constant<bool, !T::value> {};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// is_trivially_destructible()
|
||||
//
|
||||
// Determines whether the passed type `T` is trivially destructable.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++11
|
||||
// `std::is_trivially_destructible()` metafunction for platforms that have
|
||||
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
|
||||
// fully support C++11, we check whether this yields the same result as the std
|
||||
// implementation.
|
||||
//
|
||||
// NOTE: the extensions (__has_trivial_xxx) are implemented in gcc (version >=
|
||||
// 4.3) and clang. Since we are supporting libstdc++ > 4.7, they should always
|
||||
// be present. These extensions are documented at
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct is_trivially_destructible
|
||||
: std::integral_constant<bool, __has_trivial_destructor(T) &&
|
||||
std::is_destructible<T>::value>
|
||||
{
|
||||
#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
|
||||
is_trivially_destructible::value;
|
||||
static_assert(compliant || std::is_trivially_destructible<T>::value,
|
||||
"Not compliant with std::is_trivially_destructible; "
|
||||
"Standard: false, Implementation: true");
|
||||
static_assert(compliant || !std::is_trivially_destructible<T>::value,
|
||||
"Not compliant with std::is_trivially_destructible; "
|
||||
"Standard: true, Implementation: false");
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// is_trivially_default_constructible()
|
||||
//
|
||||
// Determines whether the passed type `T` is trivially default constructible.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++11
|
||||
// `std::is_trivially_default_constructible()` metafunction for platforms that
|
||||
// have incomplete C++11 support (such as libstdc++ 4.x). On any platforms that
|
||||
// do fully support C++11, we check whether this yields the same result as the
|
||||
// std implementation.
|
||||
//
|
||||
// NOTE: according to the C++ standard, Section: 20.15.4.3 [meta.unary.prop]
|
||||
// "The predicate condition for a template specialization is_constructible<T,
|
||||
// Args...> shall be satisfied if and only if the following variable
|
||||
// definition would be well-formed for some invented variable t:
|
||||
//
|
||||
// T t(declval<Args>()...);
|
||||
//
|
||||
// is_trivially_constructible<T, Args...> additionally requires that the
|
||||
// variable definition does not call any operation that is not trivial.
|
||||
// For the purposes of this check, the call to std::declval is considered
|
||||
// trivial."
|
||||
//
|
||||
// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
|
||||
// In many implementations, is_nothrow_constructible also checks if the
|
||||
// destructor throws because it is effectively noexcept(T(arg)). Same
|
||||
// applies to is_trivially_constructible, which, in these implementations, also
|
||||
// requires that the destructor is trivial.
|
||||
// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
|
||||
// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116.
|
||||
//
|
||||
// "T obj();" need to be well-formed and not call any nontrivial operation.
|
||||
// Nontrivially destructible types will cause the expression to be nontrivial.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct is_trivially_default_constructible
|
||||
: std::integral_constant<bool, __has_trivial_constructor(T) &&
|
||||
std::is_default_constructible<T>::value &&
|
||||
is_trivially_destructible<T>::value>
|
||||
{
|
||||
#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_default_constructible<T>::value ==
|
||||
is_trivially_default_constructible::value;
|
||||
static_assert(compliant || std::is_trivially_default_constructible<T>::value,
|
||||
"Not compliant with std::is_trivially_default_constructible; "
|
||||
"Standard: false, Implementation: true");
|
||||
static_assert(compliant || !std::is_trivially_default_constructible<T>::value,
|
||||
"Not compliant with std::is_trivially_default_constructible; "
|
||||
"Standard: true, Implementation: false");
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// is_trivially_copy_constructible()
|
||||
//
|
||||
// Determines whether the passed type `T` is trivially copy constructible.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++11
|
||||
// `std::is_trivially_copy_constructible()` metafunction for platforms that have
|
||||
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
|
||||
// fully support C++11, we check whether this yields the same result as the std
|
||||
// implementation.
|
||||
//
|
||||
// NOTE: `T obj(declval<const T&>());` needs to be well-formed and not call any
|
||||
// nontrivial operation. Nontrivially destructible types will cause the
|
||||
// expression to be nontrivial.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct is_trivially_copy_constructible
|
||||
: std::integral_constant<bool, __has_trivial_copy(T) &&
|
||||
std::is_copy_constructible<T>::value &&
|
||||
is_trivially_destructible<T>::value>
|
||||
{
|
||||
#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_copy_constructible<T>::value ==
|
||||
is_trivially_copy_constructible::value;
|
||||
static_assert(compliant || std::is_trivially_copy_constructible<T>::value,
|
||||
"Not compliant with std::is_trivially_copy_constructible; "
|
||||
"Standard: false, Implementation: true");
|
||||
static_assert(compliant || !std::is_trivially_copy_constructible<T>::value,
|
||||
"Not compliant with std::is_trivially_copy_constructible; "
|
||||
"Standard: true, Implementation: false");
|
||||
#endif
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// is_trivially_copy_assignable()
|
||||
//
|
||||
// Determines whether the passed type `T` is trivially copy assignable.
|
||||
//
|
||||
// This metafunction is designed to be a drop-in replacement for the C++11
|
||||
// `std::is_trivially_copy_assignable()` metafunction for platforms that have
|
||||
// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
|
||||
// fully support C++11, we check whether this yields the same result as the std
|
||||
// implementation.
|
||||
//
|
||||
// NOTE: `is_assignable<T, U>::value` is `true` if the expression
|
||||
// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
|
||||
// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
|
||||
// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
|
||||
// `is_trivially_assignable<T&, const T&>`.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct is_trivially_copy_assignable
|
||||
: std::integral_constant<
|
||||
bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
|
||||
phmap::is_copy_assignable<T>::value>
|
||||
{
|
||||
#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
|
||||
private:
|
||||
static constexpr bool compliant =
|
||||
std::is_trivially_copy_assignable<T>::value ==
|
||||
is_trivially_copy_assignable::value;
|
||||
static_assert(compliant || std::is_trivially_copy_assignable<T>::value,
|
||||
"Not compliant with std::is_trivially_copy_assignable; "
|
||||
"Standard: false, Implementation: true");
|
||||
static_assert(compliant || !std::is_trivially_copy_assignable<T>::value,
|
||||
"Not compliant with std::is_trivially_copy_assignable; "
|
||||
"Standard: true, Implementation: false");
|
||||
#endif
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// C++14 "_t" trait aliases
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
using remove_cv_t = typename std::remove_cv<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_const_t = typename std::remove_const<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_volatile_t = typename std::remove_volatile<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_cv_t = typename std::add_cv<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_const_t = typename std::add_const<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_volatile_t = typename std::add_volatile<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_reference_t = typename std::remove_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_pointer_t = typename std::remove_pointer<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using add_pointer_t = typename std::add_pointer<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using make_signed_t = typename std::make_signed<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using make_unsigned_t = typename std::make_unsigned<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_extent_t = typename std::remove_extent<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using remove_all_extents_t = typename std::remove_all_extents<T>::type;
|
||||
|
||||
template <size_t Len, size_t Align = type_traits_internal::
|
||||
default_alignment_of_aligned_storage<Len>::value>
|
||||
using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
|
||||
|
||||
template <typename T>
|
||||
using decay_t = typename std::decay<T>::type;
|
||||
|
||||
template <bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
template <bool B, typename T, typename F>
|
||||
using conditional_t = typename std::conditional<B, T, F>::type;
|
||||
|
||||
template <typename... T>
|
||||
using common_type_t = typename std::common_type<T...>::type;
|
||||
|
||||
template <typename T>
|
||||
using underlying_type_t = typename std::underlying_type<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using result_of_t = typename std::result_of<T>::type;
|
||||
|
||||
namespace type_traits_internal {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// In MSVC we can't probe std::hash or stdext::hash because it triggers a
|
||||
// static_assert instead of failing substitution. Libc++ prior to 4.0
|
||||
// also used a static_assert.
|
||||
// ----------------------------------------------------------------------
|
||||
#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
|
||||
_LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
|
||||
#define PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
|
||||
#else
|
||||
#define PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
|
||||
#endif
|
||||
|
||||
#if !PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
|
||||
template <typename Key, typename = size_t>
|
||||
struct IsHashable : std::true_type {};
|
||||
#else // PHMAP_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
|
||||
template <typename Key, typename = void>
|
||||
struct IsHashable : std::false_type {};
|
||||
|
||||
template <typename Key>
|
||||
struct IsHashable<
|
||||
Key,
|
||||
phmap::enable_if_t<std::is_convertible<
|
||||
decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
|
||||
std::size_t>::value>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
struct AssertHashEnabledHelper
|
||||
{
|
||||
private:
|
||||
static void Sink(...) {}
|
||||
struct NAT {};
|
||||
|
||||
template <class Key>
|
||||
static auto GetReturnType(int)
|
||||
-> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
|
||||
template <class Key>
|
||||
static NAT GetReturnType(...);
|
||||
|
||||
template <class Key>
|
||||
static std::nullptr_t DoIt() {
|
||||
static_assert(IsHashable<Key>::value,
|
||||
"std::hash<Key> does not provide a call operator");
|
||||
static_assert(
|
||||
std::is_default_constructible<std::hash<Key>>::value,
|
||||
"std::hash<Key> must be default constructible when it is enabled");
|
||||
static_assert(
|
||||
std::is_copy_constructible<std::hash<Key>>::value,
|
||||
"std::hash<Key> must be copy constructible when it is enabled");
|
||||
static_assert(phmap::is_copy_assignable<std::hash<Key>>::value,
|
||||
"std::hash<Key> must be copy assignable when it is enabled");
|
||||
// is_destructible is unchecked as it's implied by each of the
|
||||
// is_constructible checks.
|
||||
using ReturnType = decltype(GetReturnType<Key>(0));
|
||||
static_assert(std::is_same<ReturnType, NAT>::value ||
|
||||
std::is_same<ReturnType, size_t>::value,
|
||||
"std::hash<Key> must return size_t");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
friend void AssertHashEnabled();
|
||||
};
|
||||
|
||||
template <class... Ts>
|
||||
inline void AssertHashEnabled()
|
||||
{
|
||||
using Helper = AssertHashEnabledHelper;
|
||||
Helper::Sink(Helper::DoIt<Ts>()...);
|
||||
}
|
||||
|
||||
} // namespace type_traits_internal
|
||||
|
||||
} // namespace phmap
|
||||
|
||||
|
||||
|
||||
#endif // phmap_base_h_guard_
|
||||
Vendored
+358
@@ -0,0 +1,358 @@
|
||||
#if !defined(phmap_bits_h_guard_)
|
||||
#define phmap_bits_h_guard_
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
//
|
||||
// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
|
||||
// with modifications.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// The following guarantees declaration of the byte swap functions
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h> // NOLINT(build/include)
|
||||
#elif defined(__APPLE__)
|
||||
// Mac OS X / Darwin features
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/endian.h>
|
||||
#elif defined(__GLIBC__)
|
||||
#include <byteswap.h> // IWYU pragma: export
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include "phmap_config.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// unaligned APIs
|
||||
// -----------------------------------------------------------------------------
|
||||
// Portable handling of unaligned loads, stores, and copies.
|
||||
// On some platforms, like ARM, the copy functions can be more efficient
|
||||
// then a load and a store.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
|
||||
defined(MEMORY_SANITIZER)
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
uint16_t __sanitizer_unaligned_load16(const void *p);
|
||||
uint32_t __sanitizer_unaligned_load32(const void *p);
|
||||
uint64_t __sanitizer_unaligned_load64(const void *p);
|
||||
void __sanitizer_unaligned_store16(void *p, uint16_t v);
|
||||
void __sanitizer_unaligned_store32(void *p, uint32_t v);
|
||||
void __sanitizer_unaligned_store64(void *p, uint64_t v);
|
||||
} // extern "C"
|
||||
|
||||
namespace phmap {
|
||||
namespace bits {
|
||||
|
||||
inline uint16_t UnalignedLoad16(const void *p) {
|
||||
return __sanitizer_unaligned_load16(p);
|
||||
}
|
||||
|
||||
inline uint32_t UnalignedLoad32(const void *p) {
|
||||
return __sanitizer_unaligned_load32(p);
|
||||
}
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p) {
|
||||
return __sanitizer_unaligned_load64(p);
|
||||
}
|
||||
|
||||
inline void UnalignedStore16(void *p, uint16_t v) {
|
||||
__sanitizer_unaligned_store16(p, v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore32(void *p, uint32_t v) {
|
||||
__sanitizer_unaligned_store32(p, v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) {
|
||||
__sanitizer_unaligned_store64(p, v);
|
||||
}
|
||||
|
||||
} // namespace bits
|
||||
} // namespace phmap
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) (phmap::bits::UnalignedLoad16(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) (phmap::bits::UnalignedLoad32(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) (phmap::bits::UnalignedLoad64(_p))
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) (phmap::bits::UnalignedStore16(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) (phmap::bits::UnalignedStore32(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) (phmap::bits::UnalignedStore64(_p, _val))
|
||||
|
||||
#elif defined(UNDEFINED_BEHAVIOR_SANITIZER)
|
||||
|
||||
namespace phmap {
|
||||
namespace bits {
|
||||
|
||||
inline uint16_t UnalignedLoad16(const void *p) {
|
||||
uint16_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint32_t UnalignedLoad32(const void *p) {
|
||||
uint32_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p) {
|
||||
uint64_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
} // namespace bits
|
||||
} // namespace phmap
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) \
|
||||
(phmap::bits::UnalignedLoad16(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) \
|
||||
(phmap::bits::UnalignedLoad32(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) \
|
||||
(phmap::bits::UnalignedLoad64(_p))
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) \
|
||||
(phmap::bits::UnalignedStore16(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) \
|
||||
(phmap::bits::UnalignedStore32(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) \
|
||||
(phmap::bits::UnalignedStore64(_p, _val))
|
||||
|
||||
#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \
|
||||
defined(_M_IX86) || defined(__ppc__) || defined(__PPC__) || \
|
||||
defined(__ppc64__) || defined(__PPC64__)
|
||||
|
||||
// x86 and x86-64 can perform unaligned loads/stores directly;
|
||||
// modern PowerPC hardware can also do unaligned integer loads and stores;
|
||||
// but note: the FPU still sends unaligned loads and stores to a trap handler!
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) \
|
||||
(*reinterpret_cast<const uint16_t *>(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) \
|
||||
(*reinterpret_cast<const uint32_t *>(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) \
|
||||
(*reinterpret_cast<const uint64_t *>(_p))
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) \
|
||||
(*reinterpret_cast<uint16_t *>(_p) = (_val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) \
|
||||
(*reinterpret_cast<uint32_t *>(_p) = (_val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) \
|
||||
(*reinterpret_cast<uint64_t *>(_p) = (_val))
|
||||
|
||||
#elif defined(__arm__) && \
|
||||
!defined(__ARM_ARCH_5__) && \
|
||||
!defined(__ARM_ARCH_5T__) && \
|
||||
!defined(__ARM_ARCH_5TE__) && \
|
||||
!defined(__ARM_ARCH_5TEJ__) && \
|
||||
!defined(__ARM_ARCH_6__) && \
|
||||
!defined(__ARM_ARCH_6J__) && \
|
||||
!defined(__ARM_ARCH_6K__) && \
|
||||
!defined(__ARM_ARCH_6Z__) && \
|
||||
!defined(__ARM_ARCH_6ZK__) && \
|
||||
!defined(__ARM_ARCH_6T2__)
|
||||
|
||||
|
||||
namespace phmap {
|
||||
namespace bits {
|
||||
|
||||
struct Unaligned16Struct
|
||||
{
|
||||
uint16_t value;
|
||||
uint8_t dummy; // To make the size non-power-of-two.
|
||||
} PHMAP_ATTRIBUTE_PACKED;
|
||||
|
||||
struct Unaligned32Struct
|
||||
{
|
||||
uint32_t value;
|
||||
uint8_t dummy; // To make the size non-power-of-two.
|
||||
} PHMAP_ATTRIBUTE_PACKED;
|
||||
|
||||
} // namespace bits
|
||||
} // namespace phmap
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) \
|
||||
((reinterpret_cast<const ::phmap::bits::Unaligned16Struct *>(_p))->value)
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) \
|
||||
((reinterpret_cast<const ::phmap::bits::Unaligned32Struct *>(_p))->value)
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) \
|
||||
((reinterpret_cast< ::phmap::bits::Unaligned16Struct *>(_p))->value = (_val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) \
|
||||
((reinterpret_cast< ::phmap::bits::Unaligned32Struct *>(_p))->value = (_val))
|
||||
|
||||
namespace phmap {
|
||||
namespace bits {
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p)
|
||||
{
|
||||
uint64_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
} // namespace bits
|
||||
} // namespace phmap
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) \
|
||||
(phmap::bits::UnalignedLoad64(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) \
|
||||
(phmap::bits::UnalignedStore64(_p, _val))
|
||||
|
||||
#else
|
||||
|
||||
// PHMAP_INTERNAL_NEED_ALIGNED_LOADS is defined when the underlying platform
|
||||
// doesn't support unaligned access.
|
||||
#define PHMAP_INTERNAL_NEED_ALIGNED_LOADS
|
||||
|
||||
// These functions are provided for architectures that don't support
|
||||
// unaligned loads and stores.
|
||||
|
||||
namespace phmap {
|
||||
namespace bits {
|
||||
|
||||
inline uint16_t UnalignedLoad16(const void *p) {
|
||||
uint16_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint32_t UnalignedLoad32(const void *p) {
|
||||
uint32_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p) {
|
||||
uint64_t t;
|
||||
memcpy(&t, p, sizeof t);
|
||||
return t;
|
||||
}
|
||||
|
||||
inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
|
||||
|
||||
} // namespace bits
|
||||
} // namespace phmap
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD16(_p) (phmap::bits::UnalignedLoad16(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD32(_p) (phmap::bits::UnalignedLoad32(_p))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_LOAD64(_p) (phmap::bits::UnalignedLoad64(_p))
|
||||
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE16(_p, _val) (phmap::bits::UnalignedStore16(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE32(_p, _val) (phmap::bits::UnalignedStore32(_p, _val))
|
||||
#define PHMAP_INTERNAL_UNALIGNED_STORE64(_p, _val) (phmap::bits::UnalignedStore64(_p, _val))
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: optimization.h
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__pnacl__)
|
||||
#define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
|
||||
#elif defined(__clang__)
|
||||
// Clang will not tail call given inline volatile assembly.
|
||||
#define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
|
||||
#elif defined(__GNUC__)
|
||||
// GCC will not tail call given inline volatile assembly.
|
||||
#define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
|
||||
#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
// The __nop() intrinsic blocks the optimisation.
|
||||
#define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() __nop()
|
||||
#else
|
||||
#define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Cache line alignment
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#elif defined(__powerpc64__)
|
||||
#define PHMAP_CACHELINE_SIZE 128
|
||||
#elif defined(__aarch64__)
|
||||
// We would need to read special register ctr_el0 to find out L1 dcache size.
|
||||
// This value is a good estimate based on a real aarch64 machine.
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#elif defined(__arm__)
|
||||
// Cache line sizes for ARM: These values are not strictly correct since
|
||||
// cache line sizes depend on implementations, not architectures. There
|
||||
// are even implementations with cache line sizes configurable at boot
|
||||
// time.
|
||||
#if defined(__ARM_ARCH_5T__)
|
||||
#define PHMAP_CACHELINE_SIZE 32
|
||||
#elif defined(__ARM_ARCH_7A__)
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PHMAP_CACHELINE_SIZE
|
||||
// A reasonable default guess. Note that overestimates tend to waste more
|
||||
// space, while underestimates tend to waste more time.
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#endif
|
||||
|
||||
#define PHMAP_CACHELINE_ALIGNED __attribute__((aligned(PHMAP_CACHELINE_SIZE)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#define PHMAP_CACHELINE_ALIGNED __declspec(align(PHMAP_CACHELINE_SIZE))
|
||||
#else
|
||||
#define PHMAP_CACHELINE_SIZE 64
|
||||
#define PHMAP_CACHELINE_ALIGNED
|
||||
#endif
|
||||
|
||||
|
||||
#if PHMAP_HAVE_BUILTIN(__builtin_expect) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_PREDICT_FALSE(x) (__builtin_expect(x, 0))
|
||||
#define PHMAP_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
|
||||
#else
|
||||
#define PHMAP_PREDICT_FALSE(x) (x)
|
||||
#define PHMAP_PREDICT_TRUE(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // phmap_bits_h_guard_
|
||||
Vendored
+631
@@ -0,0 +1,631 @@
|
||||
#if !defined(phmap_config_h_guard_)
|
||||
#define phmap_config_h_guard_
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
//
|
||||
// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
|
||||
// with modifications.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Included for the __GLIBC__ macro (or similar macros on other systems).
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
// Included for __GLIBCXX__, _LIBCPP_VERSION
|
||||
#include <cstddef>
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
|
||||
// __IPHONE_8_0.
|
||||
#include <Availability.h>
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Some sanity checks
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(__CYGWIN__)
|
||||
#error "Cygwin is not supported."
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__)
|
||||
#error "phmap requires Visual Studio 2015 Update 2 or higher."
|
||||
#endif
|
||||
|
||||
// We support gcc 4.7 and later.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
|
||||
#error "phmap requires gcc 4.7 or higher."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later.
|
||||
// This corresponds to Apple Xcode version 4.5.
|
||||
#if defined(__apple_build_version__) && __apple_build_version__ < 4211165
|
||||
#error "phmap requires __apple_build_version__ of 4211165 or higher."
|
||||
#endif
|
||||
|
||||
// Enforce C++11 as the minimum.
|
||||
#if defined(__cplusplus) && !defined(_MSC_VER)
|
||||
#if __cplusplus < 201103L
|
||||
#error "C++ versions less than C++11 are not supported."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// We have chosen glibc 2.12 as the minimum
|
||||
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
|
||||
#if !__GLIBC_PREREQ(2, 12)
|
||||
#error "Minimum required version of glibc is 2.12."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_STLPORT_VERSION)
|
||||
#error "STLPort is not supported."
|
||||
#endif
|
||||
|
||||
#if CHAR_BIT != 8
|
||||
#error "phmap assumes CHAR_BIT == 8."
|
||||
#endif
|
||||
|
||||
// phmap currently assumes that an int is 4 bytes.
|
||||
#if INT_MAX < 2147483647
|
||||
#error "phmap assumes that int is at least 4 bytes. "
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Compiler Feature Checks
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __has_builtin
|
||||
#define PHMAP_HAVE_BUILTIN(x) __has_builtin(x)
|
||||
#else
|
||||
#define PHMAP_HAVE_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Checks whether `std::is_trivially_destructible<T>` is supported.
|
||||
// ----------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
|
||||
#error PHMAP_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
|
||||
#elif defined(_LIBCPP_VERSION) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \
|
||||
defined(_MSC_VER)
|
||||
#define PHMAP_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Checks whether `std::is_trivially_default_constructible<T>` is
|
||||
// supported.
|
||||
// --------------------------------------------------------------
|
||||
#if defined(PHMAP_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
|
||||
#error PHMAP_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
|
||||
#elif defined(PHMAP_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
|
||||
#error PHMAP_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
|
||||
#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
|
||||
(!defined(__clang__) && defined(__GNUC__) && \
|
||||
(__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)) && \
|
||||
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \
|
||||
(defined(_MSC_VER) && !defined(__NVCC__))
|
||||
#define PHMAP_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
|
||||
#define PHMAP_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Checks whether C++11's `thread_local` storage duration specifier is
|
||||
// supported.
|
||||
// -------------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_THREAD_LOCAL
|
||||
#error PHMAP_HAVE_THREAD_LOCAL cannot be directly set
|
||||
#elif defined(__APPLE__)
|
||||
#if __has_feature(cxx_thread_local) && \
|
||||
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
|
||||
#define PHMAP_HAVE_THREAD_LOCAL 1
|
||||
#endif
|
||||
#else // !defined(__APPLE__)
|
||||
#define PHMAP_HAVE_THREAD_LOCAL 1
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__) && defined(__clang__)
|
||||
|
||||
#if __has_include(<android/ndk-version.h>)
|
||||
#include <android/ndk-version.h>
|
||||
#endif // __has_include(<android/ndk-version.h>)
|
||||
|
||||
#if defined(__ANDROID__) && defined(__clang__) && defined(__NDK_MAJOR__) && \
|
||||
defined(__NDK_MINOR__) && \
|
||||
((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
|
||||
#undef PHMAP_HAVE_TLS
|
||||
#undef PHMAP_HAVE_THREAD_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Checks whether the __int128 compiler extension for a 128-bit
|
||||
// integral type is supported.
|
||||
// ------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_INTRINSIC_INT128
|
||||
#error PHMAP_HAVE_INTRINSIC_INT128 cannot be directly set
|
||||
#elif defined(__SIZEOF_INT128__)
|
||||
#if (defined(__clang__) && !defined(_WIN32) && !defined(__aarch64__)) || \
|
||||
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
|
||||
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
|
||||
#define PHMAP_HAVE_INTRINSIC_INT128 1
|
||||
#elif defined(__CUDACC__)
|
||||
#if __CUDACC_VER__ >= 70000
|
||||
#define PHMAP_HAVE_INTRINSIC_INT128 1
|
||||
#endif // __CUDACC_VER__ >= 70000
|
||||
#endif // defined(__CUDACC__)
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Checks whether the compiler both supports and enables exceptions.
|
||||
// ------------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_EXCEPTIONS
|
||||
#error PHMAP_HAVE_EXCEPTIONS cannot be directly set.
|
||||
#elif defined(__clang__)
|
||||
#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
|
||||
#define PHMAP_HAVE_EXCEPTIONS 1
|
||||
#endif // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
|
||||
#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
|
||||
!(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \
|
||||
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
|
||||
#define PHMAP_HAVE_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Checks whether the platform has an mmap(2) implementation as defined in
|
||||
// POSIX.1-2001.
|
||||
// -----------------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_MMAP
|
||||
#error PHMAP_HAVE_MMAP cannot be directly set
|
||||
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||
defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
|
||||
defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
|
||||
defined(__ASYLO__)
|
||||
#define PHMAP_HAVE_MMAP 1
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Checks the endianness of the platform.
|
||||
// -----------------------------------------------------------------------
|
||||
#if defined(PHMAP_IS_BIG_ENDIAN)
|
||||
#error "PHMAP_IS_BIG_ENDIAN cannot be directly set."
|
||||
#endif
|
||||
|
||||
#if defined(PHMAP_IS_LITTLE_ENDIAN)
|
||||
#error "PHMAP_IS_LITTLE_ENDIAN cannot be directly set."
|
||||
#endif
|
||||
|
||||
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define PHMAP_IS_LITTLE_ENDIAN 1
|
||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define PHMAP_IS_BIG_ENDIAN 1
|
||||
#elif defined(_WIN32)
|
||||
#define PHMAP_IS_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#error "phmap endian detection needs to be set up for your compiler"
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
|
||||
defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400
|
||||
#define PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 1
|
||||
#else
|
||||
#define PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 0
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Checks whether C++17 std::any is available by checking whether <any> exists.
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifdef PHMAP_HAVE_STD_ANY
|
||||
#error "PHMAP_HAVE_STD_ANY cannot be directly set."
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<any>) && __cplusplus >= 201703L && \
|
||||
!PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
|
||||
#define PHMAP_HAVE_STD_ANY 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PHMAP_HAVE_STD_OPTIONAL
|
||||
#error "PHMAP_HAVE_STD_OPTIONAL cannot be directly set."
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<optional>) && __cplusplus >= 201703L && \
|
||||
!PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
|
||||
#define PHMAP_HAVE_STD_OPTIONAL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PHMAP_HAVE_STD_VARIANT
|
||||
#error "PHMAP_HAVE_STD_VARIANT cannot be directly set."
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<variant>) && __cplusplus >= 201703L && \
|
||||
!PHMAP_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
|
||||
#define PHMAP_HAVE_STD_VARIANT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PHMAP_HAVE_STD_STRING_VIEW
|
||||
#error "PHMAP_HAVE_STD_STRING_VIEW cannot be directly set."
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include(<string_view>) && __cplusplus >= 201703L
|
||||
#define PHMAP_HAVE_STD_STRING_VIEW 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
|
||||
((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
|
||||
// #define PHMAP_HAVE_STD_ANY 1
|
||||
#define PHMAP_HAVE_STD_OPTIONAL 1
|
||||
#define PHMAP_HAVE_STD_VARIANT 1
|
||||
#define PHMAP_HAVE_STD_STRING_VIEW 1
|
||||
#endif
|
||||
|
||||
// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
|
||||
// SEH exception from emplace for variant<SomeStruct> when constructing the
|
||||
// struct can throw. This defeats some of variant_test and
|
||||
// variant_exception_safety_test.
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
|
||||
#define PHMAP_INTERNAL_MSVC_2017_DBG_MODE
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Sanitizer Attributes
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Sanitizer-related attributes are not "defined" in this file (and indeed
|
||||
// are not defined as such in any file). To utilize the following
|
||||
// sanitizer-related attributes within your builds, define the following macros
|
||||
// within your build using a `-D` flag, along with the given value for
|
||||
// `-fsanitize`:
|
||||
//
|
||||
// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8)
|
||||
// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only)
|
||||
// * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+)
|
||||
// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+)
|
||||
// * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// A function-like feature checking macro that is a wrapper around
|
||||
// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
|
||||
// nonzero constant integer if the attribute is supported or 0 if not.
|
||||
//
|
||||
// It evaluates to zero if `__has_attribute` is not defined by the compiler.
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifdef __has_attribute
|
||||
#define PHMAP_HAVE_ATTRIBUTE(x) __has_attribute(x)
|
||||
#else
|
||||
#define PHMAP_HAVE_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// A function-like feature checking macro that accepts C++11 style attributes.
|
||||
// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
|
||||
// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
|
||||
// find `__has_cpp_attribute`, will evaluate to 0.
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(__cplusplus) && defined(__has_cpp_attribute)
|
||||
#define PHMAP_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
|
||||
#else
|
||||
#define PHMAP_HAVE_CPP_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function Attributes
|
||||
// -----------------------------------------------------------------------------
|
||||
#if PHMAP_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_PRINTF_ATTRIBUTE(string_index, first_to_check) \
|
||||
__attribute__((__format__(__printf__, string_index, first_to_check)))
|
||||
#define PHMAP_SCANF_ATTRIBUTE(string_index, first_to_check) \
|
||||
__attribute__((__format__(__scanf__, string_index, first_to_check)))
|
||||
#else
|
||||
#define PHMAP_PRINTF_ATTRIBUTE(string_index, first_to_check)
|
||||
#define PHMAP_SCANF_ATTRIBUTE(string_index, first_to_check)
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(always_inline) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#define PHMAP_HAVE_ATTRIBUTE_ALWAYS_INLINE 1
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_NOINLINE __attribute__((noinline))
|
||||
#define PHMAP_HAVE_ATTRIBUTE_NOINLINE 1
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(disable_tail_calls)
|
||||
#define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
|
||||
#define PHMAP_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))
|
||||
#elif defined(__GNUC__) && !defined(__clang__)
|
||||
#define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
|
||||
#define PHMAP_ATTRIBUTE_NO_TAIL_CALL \
|
||||
__attribute__((optimize("no-optimize-sibling-calls")))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_TAIL_CALL
|
||||
#define PHMAP_HAVE_ATTRIBUTE_NO_TAIL_CALL 0
|
||||
#endif
|
||||
|
||||
#if (PHMAP_HAVE_ATTRIBUTE(weak) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))) && \
|
||||
!(defined(__llvm__) && defined(_WIN32))
|
||||
#undef PHMAP_ATTRIBUTE_WEAK
|
||||
#define PHMAP_ATTRIBUTE_WEAK __attribute__((weak))
|
||||
#define PHMAP_HAVE_ATTRIBUTE_WEAK 1
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_WEAK
|
||||
#define PHMAP_HAVE_ATTRIBUTE_WEAK 0
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index)))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NONNULL(...)
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
#define PHMAP_ATTRIBUTE_NORETURN __declspec(noreturn)
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(ADDRESS_SANITIZER)
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(MEMORY_SANITIZER)
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_MEMORY
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(THREAD_SANITIZER)
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_THREAD
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
(defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_UNDEFINED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_CFI
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
|
||||
__attribute__((no_sanitize("safe-stack")))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_NO_SANITIZE_SAFESTACK
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(returns_nonnull) || \
|
||||
(defined(__GNUC__) && \
|
||||
(__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \
|
||||
!defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_RETURNS_NONNULL
|
||||
#endif
|
||||
|
||||
#ifdef PHMAP_HAVE_ATTRIBUTE_SECTION
|
||||
#error PHMAP_HAVE_ATTRIBUTE_SECTION cannot be directly set
|
||||
#elif (PHMAP_HAVE_ATTRIBUTE(section) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))) && \
|
||||
!defined(__APPLE__) && PHMAP_HAVE_ATTRIBUTE_WEAK
|
||||
#define PHMAP_HAVE_ATTRIBUTE_SECTION 1
|
||||
#ifndef PHMAP_ATTRIBUTE_SECTION
|
||||
#define PHMAP_ATTRIBUTE_SECTION(name) \
|
||||
__attribute__((section(#name))) __attribute__((noinline))
|
||||
#endif
|
||||
#ifndef PHMAP_ATTRIBUTE_SECTION_VARIABLE
|
||||
#define PHMAP_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
|
||||
#endif
|
||||
#ifndef PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS
|
||||
#define PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS(name) \
|
||||
extern char __start_##name[] PHMAP_ATTRIBUTE_WEAK; \
|
||||
extern char __stop_##name[] PHMAP_ATTRIBUTE_WEAK
|
||||
#endif
|
||||
#ifndef PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS
|
||||
#define PHMAP_INIT_ATTRIBUTE_SECTION_VARS(name)
|
||||
#define PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS(name)
|
||||
#endif
|
||||
#define PHMAP_ATTRIBUTE_SECTION_START(name) \
|
||||
(reinterpret_cast<void *>(__start_##name))
|
||||
#define PHMAP_ATTRIBUTE_SECTION_STOP(name) \
|
||||
(reinterpret_cast<void *>(__stop_##name))
|
||||
#else // !PHMAP_HAVE_ATTRIBUTE_SECTION
|
||||
#define PHMAP_HAVE_ATTRIBUTE_SECTION 0
|
||||
#define PHMAP_ATTRIBUTE_SECTION(name)
|
||||
#define PHMAP_ATTRIBUTE_SECTION_VARIABLE(name)
|
||||
#define PHMAP_INIT_ATTRIBUTE_SECTION_VARS(name)
|
||||
#define PHMAP_DEFINE_ATTRIBUTE_SECTION_VARS(name)
|
||||
#define PHMAP_DECLARE_ATTRIBUTE_SECTION_VARS(name)
|
||||
#define PHMAP_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0))
|
||||
#define PHMAP_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0))
|
||||
#endif // PHMAP_ATTRIBUTE_SECTION
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(force_align_arg_pointer) || \
|
||||
(defined(__GNUC__) && !defined(__clang__))
|
||||
#if defined(__i386__)
|
||||
#define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \
|
||||
__attribute__((force_align_arg_pointer))
|
||||
#define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
|
||||
#elif defined(__x86_64__)
|
||||
#define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (1)
|
||||
#define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
|
||||
#else // !__i386__ && !__x86_64
|
||||
#define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
|
||||
#define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
|
||||
#endif // __i386__
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
|
||||
#define PHMAP_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(nodiscard)
|
||||
#define PHMAP_MUST_USE_RESULT [[nodiscard]]
|
||||
#elif defined(__clang__) && PHMAP_HAVE_ATTRIBUTE(warn_unused_result)
|
||||
#define PHMAP_MUST_USE_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define PHMAP_MUST_USE_RESULT
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_HOT __attribute__((hot))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_HOT
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_COLD __attribute__((cold))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_COLD
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
|
||||
!defined(PHMAP_NO_XRAY_ATTRIBUTES)
|
||||
#define PHMAP_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
|
||||
#define PHMAP_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
|
||||
#if PHMAP_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
|
||||
#define PHMAP_XRAY_LOG_ARGS(N) \
|
||||
[[clang::xray_always_instrument, clang::xray_log_args(N)]]
|
||||
#else
|
||||
#define PHMAP_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]]
|
||||
#endif
|
||||
#else
|
||||
#define PHMAP_XRAY_ALWAYS_INSTRUMENT
|
||||
#define PHMAP_XRAY_NEVER_INSTRUMENT
|
||||
#define PHMAP_XRAY_LOG_ARGS(N)
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_CPP_ATTRIBUTE(clang::reinitializes)
|
||||
#define PHMAP_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_REINITIALIZES
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#undef PHMAP_ATTRIBUTE_UNUSED
|
||||
#define PHMAP_ATTRIBUTE_UNUSED __attribute__((__unused__))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_UNUSED
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec")))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_INITIAL_EXEC
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_PACKED __attribute__((__packed__))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_PACKED
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__))
|
||||
#define PHMAP_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))
|
||||
#else
|
||||
#define PHMAP_ATTRIBUTE_FUNC_ALIGN(bytes)
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
|
||||
#define PHMAP_CONST_INIT [[clang::require_constant_initialization]]
|
||||
#else
|
||||
#define PHMAP_CONST_INIT
|
||||
#endif // PHMAP_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Figure out SSE support
|
||||
// ----------------------------------------------------------------------
|
||||
#ifndef PHMAP_HAVE_SSE2
|
||||
#if defined(__SSE2__) || \
|
||||
(defined(_MSC_VER) && \
|
||||
(defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
|
||||
#define PHMAP_HAVE_SSE2 1
|
||||
#else
|
||||
#define PHMAP_HAVE_SSE2 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PHMAP_HAVE_SSSE3
|
||||
#ifdef __SSSE3__
|
||||
#define PHMAP_HAVE_SSSE3 1
|
||||
#else
|
||||
#define PHMAP_HAVE_SSSE3 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_SSSE3 && !PHMAP_HAVE_SSE2
|
||||
#error "Bad configuration!"
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_SSE2
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#if PHMAP_HAVE_SSSE3
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
|
||||
#endif // phmap_config_h_guard_
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
#if !defined(phmap_utils_h_guard_)
|
||||
#define phmap_utils_h_guard_
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
//
|
||||
// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
|
||||
// with modifications.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // phmap_utils_h_guard_
|
||||
Reference in New Issue
Block a user