Skip to content

Commit fa5a89f

Browse files
authored
Fix incorrect code in parallel_node_hash_set emplace. (#293)
* Fix incorrect code in `parallel_node_hash_set` emplace. * Add test for issue #292.
1 parent 4e410c7 commit fa5a89f

File tree

3 files changed

+37
-20
lines changed

3 files changed

+37
-20
lines changed

parallel_hashmap/phmap.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3159,8 +3159,8 @@ class parallel_hash_set
31593159
Inner& inner = sets_[subidx(hashval)];
31603160
auto& set = inner.set_;
31613161
UniqueLock m(inner);
3162-
typename EmbeddedSet::template InsertSlotWithHash<true> f { inner, std::move(*slot), hashval };
3163-
return make_rv(PolicyTraits::apply(f, elem));
3162+
typename EmbeddedSet::template InsertSlotWithHash<true> f { inner.set_, std::move(*slot), hashval };
3163+
return make_rv(&inner, PolicyTraits::apply(std::move(f), elem));
31643164
}
31653165

31663166
template <class... Args>
@@ -3227,15 +3227,15 @@ class parallel_hash_set
32273227
std::pair<iterator, bool> emplace(Args&&... args) {
32283228
typename phmap::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type raw;
32293229
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
3230-
size_t hashval = this->hash(PolicyTraits::key(slot));
3231-
32323230
PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
3231+
32333232
const auto& elem = PolicyTraits::element(slot);
3233+
size_t hashval = this->hash(PolicyTraits::key(slot));
32343234
Inner& inner = sets_[subidx(hashval)];
32353235
auto& set = inner.set_;
32363236
UniqueLock m(inner);
3237-
typename EmbeddedSet::template InsertSlotWithHash<true> f { inner, std::move(*slot), hashval };
3238-
return make_rv(PolicyTraits::apply(f, elem));
3237+
typename EmbeddedSet::template InsertSlotWithHash<true> f { inner.set_, std::move(*slot), hashval };
3238+
return make_rv(&inner, PolicyTraits::apply(std::move(f), elem));
32393239
}
32403240

32413241
template <class... Args>

parallel_hashmap/phmap_base.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -424,18 +424,30 @@ namespace priv {
424424
template <class Policy, class = void>
425425
struct hash_policy_traits
426426
{
427+
// The type of the keys stored in the hashtable.
428+
using key_type = typename Policy::key_type;
427429
private:
428-
struct ReturnKey
429-
{
430-
// We return `Key` here.
431-
// When Key=T&, we forward the lvalue reference.
432-
// When Key=T, we return by value to avoid a dangling reference.
433-
// eg, for string_hash_map.
434-
template <class Key, class... Args>
435-
Key operator()(Key&& k, const Args&...) const {
436-
return std::forward<Key>(k);
437-
}
438-
};
430+
struct ReturnKey {
431+
template <class Key,
432+
phmap::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
433+
static key_type& Impl(Key&& k, int) {
434+
return *const_cast<key_type*>(std::addressof(std::forward<Key>(k)));
435+
}
436+
437+
template <class Key>
438+
static Key Impl(Key&& k, char) {
439+
return std::forward<Key>(k);
440+
}
441+
442+
// When Key=T&, we forward the lvalue reference.
443+
// When Key=T, we return by value to avoid a dangling reference.
444+
// eg, for string_hash_map.
445+
template <class Key, class... Args>
446+
auto operator()(Key&& k, const Args&...) const
447+
-> decltype(Impl(std::forward<Key>(k), 0)) {
448+
return Impl(std::forward<Key>(k), 0);
449+
}
450+
};
439451

440452
template <class P = Policy, class = void>
441453
struct ConstantIteratorsImpl : std::false_type {};
@@ -448,9 +460,6 @@ struct hash_policy_traits
448460
// The actual object stored in the hash table.
449461
using slot_type = typename Policy::slot_type;
450462

451-
// The type of the keys stored in the hashtable.
452-
using key_type = typename Policy::key_type;
453-
454463
// The argument type for insertions into the hashtable. This is different
455464
// from value_type for increased performance. See initializer_list constructor
456465
// and insert() member functions for more details.

tests/node_hash_set_test.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ TEST(THIS_TEST_NAME, MergeExtractInsert) {
105105
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
106106
}
107107

108+
TEST(THIS_TEST_NAME, Emplace) {
109+
using Thing = std::tuple<size_t, double>;
110+
phmap::THIS_HASH_SET<Thing> hs;
111+
hs.emplace(Thing(0, 1.25));
112+
hs.emplace(0, 1.3);
113+
assert(hs.find(Thing(0, 1.3)) != hs.end());
114+
}
115+
108116
} // namespace
109117
} // namespace priv
110118
} // namespace phmap

0 commit comments

Comments
 (0)