Skip to content

Commit 2f12d8c

Browse files
committed
WIP Transactional hash_map
1 parent f8587be commit 2f12d8c

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#pragma once
2+
3+
#include "testing/config.hpp"
4+
5+
#include "trade_v1/trade.hpp"
6+
7+
#include "polyfill_v1/memory.hpp"
8+
#include <functional>
9+
#include <utility>
10+
11+
namespace testing {
12+
13+
template <class Key,
14+
class Mapped,
15+
class Hash = std::hash<Key>,
16+
class KeyEqual = std::equal_to<Key>>
17+
struct hash_map;
18+
19+
class hash_map_private {
20+
template <class, class, class, class> friend struct hash_map;
21+
22+
static size_t next_capacity(size_t capacity);
23+
};
24+
25+
template <class Key, class Mapped, class Hash, class KeyEqual> struct hash_map {
26+
using size_type = size_t;
27+
28+
using key_type = Key;
29+
using mapped_type = Mapped;
30+
using value_type = std::pair<const Key, Mapped>;
31+
32+
hash_map() : m_item_count(0), m_buckets_count(0), m_buckets(nullptr) {}
33+
34+
size_type size() const {
35+
return trade::atomically([&]() { return m_item_count.load(); });
36+
}
37+
38+
bool empty() const {
39+
return trade::atomically([&]() { return m_item_count == 0; });
40+
}
41+
42+
void clear() {
43+
trade::atomically([&]() {
44+
m_item_count = 0;
45+
m_buckets_count = 0;
46+
m_buckets = nullptr;
47+
});
48+
}
49+
50+
void swap(hash_map &that) {
51+
trade::atomically([&]() {
52+
std::swap(m_item_count.ref(), that.m_item_count.ref());
53+
std::swap(m_buckets_count.ref(), that.m_buckets_count.ref());
54+
std::swap(m_buckets.ref(), that.m_buckets.ref());
55+
});
56+
}
57+
58+
private:
59+
struct node {
60+
template <class ForwardableKey, class ForwardableMapped>
61+
node(ForwardableKey &&key, ForwardableMapped &&value)
62+
: m_next(nullptr), m_value(std::forward<ForwardableKey>(key),
63+
std::forward<ForwardableMapped>(value)) {}
64+
trade::atom<std::shared_ptr<node>> m_next;
65+
std::pair<const Key, Mapped> m_value;
66+
};
67+
68+
trade::atom<size_type> m_item_count;
69+
trade::atom<size_type> m_buckets_count;
70+
trade::atom<std::shared_ptr<node[]>> m_buckets;
71+
};
72+
73+
} // namespace testing

internals/library/hash_map.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "testing/hash_map.hpp"
2+
3+
static const size_t s_capacities[] = {
4+
3, 7, 13, 31, 61, 127,
5+
251, 509, 1021, 2039, 4093, 8191,
6+
16381, 32749, 65521, 131071, 262139, 524287,
7+
1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
8+
67108859, 134217689, 268435399, 536870909, 1073741789};
9+
10+
size_t testing::hash_map_private::next_capacity(size_t capacity) {
11+
size_t n = sizeof(s_capacities) / sizeof(*s_capacities);
12+
for (size_t i = 0; i < n; ++i)
13+
if (capacity < s_capacities[i])
14+
return s_capacities[i];
15+
return capacity;
16+
}

internals/testing/hash_map_test.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include "testing/hash_map.hpp"
2+
3+
#include "polyfill_v1/memory.hpp"
4+
5+
#include "testing_v1/test.hpp"
6+
7+
#include <string>
8+
9+
using namespace testing_v1;
10+
11+
using namespace testing;
12+
using namespace trade;
13+
14+
auto hash_map_test = test([]() {
15+
hash_map<std::string, int> map1;
16+
hash_map<std::string, int> map2;
17+
18+
map1.clear();
19+
20+
map1.swap(map2);
21+
22+
verify(map1.size() == 0);
23+
});

0 commit comments

Comments
 (0)