Merge pull request #165 from greg7mdp/disable_locking

Allow swap() to work with parallel hash maps/sets with different mutex types, so you can use the same container with or without locking.
This commit is contained in:
Gregory Popovitch
2022-09-12 11:04:17 -04:00
committed by GitHub
4 changed files with 56 additions and 11 deletions
+26 -11
View File
@@ -3372,6 +3372,11 @@ public:
fCallback(set);
}
// unsafe, for internal use only
Inner& get_inner(size_t idx) {
return sets_[idx];
}
// Extension API: support for heterogeneous keys.
//
// std::unordered_set<std::string> s;
@@ -3473,15 +3478,20 @@ public:
return it == end() ? node_type() : extract(const_iterator{it});
}
void swap(parallel_hash_set& that) noexcept(
IsNoThrowSwappable<EmbeddedSet>() &&
(!AllocTraits::propagate_on_container_swap::value ||
IsNoThrowSwappable<allocator_type>())) {
template<class Mtx2_>
void swap(parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc>& that)
noexcept(IsNoThrowSwappable<EmbeddedSet>() &&
(!AllocTraits::propagate_on_container_swap::value ||
IsNoThrowSwappable<allocator_type>()))
{
using std::swap;
using Lockable2 = phmap::LockableImpl<Mtx2_>;
for (size_t i=0; i<num_tables; ++i)
{
typename Lockable::UniqueLocks l(sets_[i], that.sets_[i]);
swap(sets_[i].set_, that.sets_[i].set_);
typename Lockable::UniqueLock l(sets_[i]);
typename Lockable2::UniqueLock l2(that.get_inner(i));
swap(sets_[i].set_, that.get_inner(i).set_);
}
}
@@ -3620,8 +3630,11 @@ public:
return !(a == b);
}
template<class Mtx2_>
friend void swap(parallel_hash_set& a,
parallel_hash_set& b) noexcept(noexcept(a.swap(b))) {
parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc>& b)
noexcept(noexcept(a.swap(b)))
{
a.swap(b);
}
@@ -3700,14 +3713,16 @@ private:
// TODO(alkis): Optimize this assuming *this and that don't overlap.
// --------------------------------------------------------------------
parallel_hash_set& move_assign(parallel_hash_set&& that, std::true_type) {
parallel_hash_set tmp(std::move(that));
template<class Mtx2_>
parallel_hash_set& move_assign(parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc>&& that, std::true_type) {
parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc> tmp(std::move(that));
swap(tmp);
return *this;
}
parallel_hash_set& move_assign(parallel_hash_set&& that, std::false_type) {
parallel_hash_set tmp(std::move(that), alloc_ref());
template<class Mtx2_>
parallel_hash_set& move_assign(parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc>&& that, std::false_type) {
parallel_hash_set<N, RefSet, Mtx2_, Policy, Hash, Eq, Alloc> tmp(std::move(that), alloc_ref());
swap(tmp);
return *this;
}
+10
View File
@@ -22,6 +22,10 @@
#define THIS_EXTRA_TPL_PARAMS
#endif
#ifndef THIS_EXTRA_TPL_PARAMS_NULLMUTEX
#define THIS_EXTRA_TPL_PARAMS_NULLMUTEX
#endif
#include "parallel_hashmap/phmap.h"
#if defined(PHMAP_HAVE_STD_ANY)
@@ -62,6 +66,12 @@ template <class K, class V, class H = phmap::priv::hash_default_hash<K>,
class Alloc = phmap::priv::Allocator<
phmap::priv::Pair<const K, V>>>
using ThisMap = THIS_HASH_MAP<K, V, H, Eq, Alloc THIS_EXTRA_TPL_PARAMS>;
template <class K, class V, class H = phmap::priv::hash_default_hash<K>,
class Eq = phmap::priv::hash_default_eq<K>,
class Alloc = phmap::priv::Allocator<
phmap::priv::Pair<const K, V>>>
using ThisMap_NullMutex = THIS_HASH_MAP<K, V, H, Eq, Alloc THIS_EXTRA_TPL_PARAMS_NULLMUTEX>;
static_assert(!std::is_standard_layout<NonStandardLayout>(), "");
@@ -9,4 +9,6 @@
#define THIS_EXTRA_TPL_PARAMS , 4, boost::upgrade_mutex
#endif
#define THIS_EXTRA_TPL_PARAMS_NULLMUTEX , 4, phmap::NullMutex
#include "parallel_hash_map_test.cc"
+18
View File
@@ -9,6 +9,24 @@ namespace phmap {
namespace priv {
namespace {
TEST(THIS_TEST_NAME, Swap) {
using Map = ThisMap<int, int>;
using MapB = ThisMap_NullMutex<int, int>;
Map t;
EXPECT_TRUE(t.find(0) == t.end());
auto res = t.emplace(0, 1);
EXPECT_TRUE(res.second);
EXPECT_EQ(1, t.size());
MapB u;
t.swap(u);
EXPECT_EQ(0, t.size());
EXPECT_EQ(1, u.size());
EXPECT_TRUE(t.find(0) == t.end());
EXPECT_TRUE(u[0] == 1);
}
TEST(THIS_TEST_NAME, IfContains) {
// ----------------
// test if_contains