diff --git a/README.md b/README.md index fc09355..fda6fdd 100644 --- a/README.md +++ b/README.md @@ -12,15 +12,18 @@ This repository aims to provide an set of excellent hash map implementations, wi - **Memory friendly**: low memory usage, although a little higher than [sparsepp](https://github.com/greg7mdp/sparsepp) -- support **heterogeneous lookup** +- supports **heterogeneous lookup** -- **Tested** on Windows (vs2015 & vs2017), linux (g++ 5, 6, 7, 8, clang++ 3.9, 4.0, 5.0) and MacOS (g++ and clang++) - click on travis [![Build Status](https://travis-ci.org/greg7mdp/parallel-hashmap.svg?branch=master)](https://travis-ci.org/greg7mdp/parallel-hashmap) and appveyor [![Build Status](https://ci.appveyor.com/api/projects/status/86kc657lp4cja8ju?svg=true)](https://ci.appveyor.com/project/greg7mdp/parallel-hashmap) icons for detailed test status. +- easy to **forward declare**: just include `phmap_fwd_decl.h` in your header files to forward declare Parallel Hashmap containers. This header is only 130 lines including comments. + +- **Tested** on Windows (vs2015 & vs2017), linux (g++ 5, 6, 7, 8, clang++ 3.9, 4.0, 5.0) and MacOS (g++ and clang++) - click on travis and appveyor icons above for detailed test status. -## Very fast *and* memory friendly +## Fast *and* memory friendly Click here [For a full writeup explaining the design and benefits of the Parallel Hashmap](https://greg7mdp.github.io/parallel-hashmap/). +The hashmaps provided here are built upon those opensourced by Google in the Abseil library. They use closed hashing, where values are stored directly into a memory array, avoiding memory indirections. By using parallel SSE2 instructions, these hashmaps are able to look up items by checking 16 slots in parallel, allowing the implementation to remain fast even when the table is filled up to 87.5% capacity. > **IMPORTANT:** This repository borrows code from the [abseil-cpp](https://github.com/abseil/abseil-cpp) repository, with modifications, and may behave differently from the original. This repository is an independent work, with no guarantees implied or provided by the authors. Please go to [abseil-cpp](https://github.com/abseil/abseil-cpp) for the official Abseil libraries. @@ -28,7 +31,7 @@ Click here [For a full writeup explaining the design and benefits of the Paralle Copy the parallel_hashmap directory to your project. Update your include path. That's all. -> cmake configuration files (CMakeLists.txt) are provided for building the tests and examples. Command for building and running the tests is: `mkdir build && cd build && cmake -DPHMAP_BUILD_TESTS=ON .. && cmake --build . && make test` +> A cmake configuration files (CMakeLists.txt) is provided for building the tests and examples. Command for building and running the tests is: `mkdir build && cd build && cmake -DPHMAP_BUILD_TESTS=ON .. && cmake --build . && make test` ## Example diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index fa6f470..e5672d3 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -51,6 +51,7 @@ #include "phmap_bits.h" #include "phmap_base.h" #include "phmap_utils.h" +#include "phmap_fwd_decl.h" #if PHMAP_HAVE_STD_STRING_VIEW #include @@ -3994,14 +3995,6 @@ public: // hash_default // -------------------------------------------------------------------------- -// The hash of an object of type T is computed by using phmap::Hash. -template -struct HashEq -{ - using Hash = phmap::Hash; - using Eq = std::equal_to; -}; - #if 0 struct int64_t_hash @@ -4091,13 +4084,6 @@ struct HashEq> : HashEq {}; template struct HashEq> : HashEq {}; -template -using hash_default_hash = typename container_internal::HashEq::Hash; - -template -using hash_default_eq = typename container_internal::HashEq::Eq; - - namespace hashtable_debug_internal { // -------------------------------------------------------------------------- @@ -4199,10 +4185,7 @@ public: // slots (open, deleted, and empty) within the hash set. // * Returns `void` from the `erase(iterator)` overload. // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator> +template // default values in phmap_fwd_decl.h class flat_hash_set : public phmap::container_internal::raw_hash_set< phmap::container_internal::FlatHashSetPolicy, Hash, Eq, Alloc> @@ -4262,10 +4245,7 @@ public: // slots (open, deleted, and empty) within the hash map. // * Returns `void` from the `erase(iterator)` overload. // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator>> +template // default values in phmap_fwd_decl.h class flat_hash_map : public phmap::container_internal::raw_hash_map< phmap::container_internal::FlatHashMapPolicy, Hash, Eq, Alloc> { @@ -4323,10 +4303,7 @@ public: // slots (open, deleted, and empty) within the hash set. // * Returns `void` from the `erase(iterator)` overload. // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator> +template // default values in phmap_fwd_decl.h class node_hash_set : public phmap::container_internal::raw_hash_set< phmap::container_internal::NodeHashSetPolicy, Hash, Eq, Alloc> @@ -4384,10 +4361,7 @@ public: // slots (open, deleted, and empty) within the hash map. // * Returns `void` from the `erase(iterator)` overload. // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator>> +template // default values in phmap_fwd_decl.h class node_hash_map : public phmap::container_internal::raw_hash_map< phmap::container_internal::NodeHashMapPolicy, Hash, Eq, @@ -4437,12 +4411,7 @@ public: // ----------------------------------------------------------------------------- // phmap::parallel_flat_hash_set // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator, - size_t N = 4, - class Mutex = phmap::NullMutex> +template // default values in phmap_fwd_decl.h class parallel_flat_hash_set : public phmap::container_internal::parallel_hash_set< N, phmap::container_internal::raw_hash_set, Mutex, @@ -4487,14 +4456,9 @@ public: }; // ----------------------------------------------------------------------------- -// phmap::parallel_flat_hash_map +// phmap::parallel_flat_hash_map - default values in phmap_fwd_decl.h // ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator>, - size_t N = 4, // 2**N submaps - class Mutex = phmap::NullMutex> // use phmap::Mutex to enable internal locks +template class parallel_flat_hash_map : public phmap::container_internal::parallel_hash_map< N, phmap::container_internal::raw_hash_set, Mutex, phmap::container_internal::FlatHashMapPolicy, @@ -4544,24 +4508,7 @@ public: // ----------------------------------------------------------------------------- // phmap::parallel_node_hash_set // ----------------------------------------------------------------------------- -// An `phmap::node_hash_set` is an unordered associative container which -// has been optimized for both speed and memory footprint in most common use -// cases. Its interface is similar to that of `std::unordered_set` with the -// following notable differences: -// -// * Supports heterogeneous lookup, through `find()`, `operator[]()` and -// `insert()`, provided that the map is provided a compatible heterogeneous -// hashing function and equality operator. -// * Contains a `capacity()` member function indicating the number of element -// slots (open, deleted, and empty) within the hash set. -// * Returns `void` from the `erase(iterator)` overload. -// ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator, - size_t N = 4, - class Mutex = phmap::NullMutex> +template class parallel_node_hash_set : public phmap::container_internal::parallel_hash_set< N, phmap::container_internal::raw_hash_set, Mutex, @@ -4607,25 +4554,7 @@ public: // ----------------------------------------------------------------------------- // phmap::parallel_node_hash_map // ----------------------------------------------------------------------------- -// -// An `phmap::node_hash_map` is an unordered associative container which -// has been optimized for both speed and memory footprint in most common use -// cases. Its interface is similar to that of `std::unordered_map` with -// the following notable differences: -// -// * Supports heterogeneous lookup, through `find()`, `operator[]()` and -// `insert()`, provided that the map is provided a compatible heterogeneous -// hashing function and equality operator. -// * Contains a `capacity()` member function indicating the number of element -// slots (open, deleted, and empty) within the hash map. -// * Returns `void` from the `erase(iterator)` overload. -// ----------------------------------------------------------------------------- -template , - class Eq = phmap::container_internal::hash_default_eq, - class Alloc = std::allocator>, - size_t N = 4, - class Mutex = phmap::NullMutex> +template class parallel_node_hash_map : public phmap::container_internal::parallel_hash_map< N, phmap::container_internal::raw_hash_set, Mutex, diff --git a/parallel_hashmap/phmap_fwd_decl.h b/parallel_hashmap/phmap_fwd_decl.h new file mode 100644 index 0000000..9f4ae5f --- /dev/null +++ b/parallel_hashmap/phmap_fwd_decl.h @@ -0,0 +1,130 @@ +#if !defined(phmap_fwd_decl_h_guard_) +#define phmap_fwd_decl_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. +// --------------------------------------------------------------------------- + +namespace std +{ + template class allocator; + template struct pair; +} + +namespace phmap { + + template struct Hash; + template struct EqualTo; + + class NullMutex; + + namespace container_internal { + + // The hash of an object of type T is computed by using phmap::Hash. + template + struct HashEq + { + using Hash = phmap::Hash; + using Eq = phmap::EqualTo; + }; + + + template + using hash_default_hash = typename container_internal::HashEq::Hash; + + template + using hash_default_eq = typename container_internal::HashEq::Eq; + + } // namespace container_internal + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator> + class flat_hash_set; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator>> + class flat_hash_map; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator> + class node_hash_set; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator>> + class node_hash_map; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator, + size_t N = 4, // 2**N submaps + class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks + class parallel_flat_hash_set; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator>, + size_t N = 4, // 2**N submaps + class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks + class parallel_flat_hash_map; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator, + size_t N = 4, // 2**N submaps + class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks + class parallel_node_hash_set; + + template , + class Eq = phmap::container_internal::hash_default_eq, + class Alloc = std::allocator>, + size_t N = 4, // 2**N submaps + class Mutex = phmap::NullMutex> // use std::mutex to enable internal locks + class parallel_node_hash_map; + + + +} // namespace phmap + + +#endif // phmap_fwd_decl_h_guard_ diff --git a/parallel_hashmap/phmap_utils.h b/parallel_hashmap/phmap_utils.h index 53527e6..d188d2c 100644 --- a/parallel_hashmap/phmap_utils.h +++ b/parallel_hashmap/phmap_utils.h @@ -44,6 +44,15 @@ namespace phmap template T phmap_min(T a, T b) { return a < b ? a : b; } template T phmap_max(T a, T b) { return a >= b ? a : b; } +template +struct EqualTo +{ + inline size_t operator()(const T& a, const T& b) const + { + return std::equal_to()(a, b); + } +}; + template struct Hash {