-
Notifications
You must be signed in to change notification settings - Fork 3
/
art.hpp
193 lines (138 loc) · 4.99 KB
/
art.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Copyright 2019-2024 Laurynas Biveinis
#ifndef UNODB_DETAIL_ART_HPP
#define UNODB_DETAIL_ART_HPP
#include "global.hpp"
// IWYU pragma: no_include <__fwd/ostream.h>
#include <cstddef>
#include <cstdint>
#include <iosfwd> // IWYU pragma: keep
#include <optional>
#include "art_common.hpp"
#include "art_internal.hpp"
#include "assert.hpp"
#include "node_type.hpp"
namespace unodb {
namespace detail {
struct node_header;
template <class, template <class> class, class, class, template <class> class,
template <class, class> class>
struct basic_art_policy; // IWYU pragma: keep
using node_ptr = basic_node_ptr<node_header>;
template <class Header, class Db>
[[nodiscard]] auto make_db_leaf_ptr(art_key, value_view, Db &);
struct impl_helpers;
} // namespace detail
class db final {
public:
using get_result = std::optional<value_view>;
// Creation and destruction
db() noexcept = default;
~db() noexcept;
// TODO(laurynas): implement copy and move operations
db(const db &) = delete;
db(db &&) = delete;
db &operator=(const db &) = delete;
db &operator=(db &&) = delete;
// Querying
[[nodiscard, gnu::pure]] get_result get(key search_key) const noexcept;
[[nodiscard, gnu::pure]] auto empty() const noexcept {
return root == nullptr;
}
// Modifying
// Cannot be called during stack unwinding with std::uncaught_exceptions() > 0
[[nodiscard]] bool insert(key insert_key, value_view v);
[[nodiscard]] bool remove(key remove_key);
void clear() noexcept;
// Stats
// Return current memory use by tree nodes in bytes.
[[nodiscard, gnu::pure]] constexpr auto get_current_memory_use()
const noexcept {
return current_memory_use;
}
template <node_type NodeType>
[[nodiscard, gnu::pure]] constexpr auto get_node_count() const noexcept {
return node_counts[as_i<NodeType>];
}
// cppcheck-suppress returnByReference
[[nodiscard, gnu::pure]] constexpr auto get_node_counts() const noexcept {
return node_counts;
}
template <node_type NodeType>
[[nodiscard, gnu::pure]] constexpr auto get_growing_inode_count()
const noexcept {
return growing_inode_counts[internal_as_i<NodeType>];
}
// cppcheck-suppress returnByReference
[[nodiscard, gnu::pure]] constexpr auto get_growing_inode_counts()
const noexcept {
return growing_inode_counts;
}
template <node_type NodeType>
[[nodiscard, gnu::pure]] constexpr auto get_shrinking_inode_count()
const noexcept {
return shrinking_inode_counts[internal_as_i<NodeType>];
}
// cppcheck-suppress returnByReference
[[nodiscard, gnu::pure]] constexpr auto get_shrinking_inode_counts()
const noexcept {
return shrinking_inode_counts;
}
[[nodiscard, gnu::pure]] constexpr auto get_key_prefix_splits()
const noexcept {
return key_prefix_splits;
}
// Public utils
[[nodiscard, gnu::const]] static constexpr auto key_found(
const get_result &result) noexcept {
return static_cast<bool>(result);
}
// Debugging
[[gnu::cold]] UNODB_DETAIL_NOINLINE void dump(std::ostream &os) const;
private:
void delete_root_subtree() noexcept;
constexpr void increase_memory_use(std::size_t delta) noexcept {
UNODB_DETAIL_ASSERT(delta > 0);
current_memory_use += delta;
}
constexpr void decrease_memory_use(std::size_t delta) noexcept {
UNODB_DETAIL_ASSERT(delta > 0);
UNODB_DETAIL_ASSERT(delta <= current_memory_use);
current_memory_use -= delta;
}
constexpr void increment_leaf_count(std::size_t leaf_size) noexcept {
increase_memory_use(leaf_size);
++node_counts[as_i<node_type::LEAF>];
}
constexpr void decrement_leaf_count(std::size_t leaf_size) noexcept {
decrease_memory_use(leaf_size);
UNODB_DETAIL_ASSERT(node_counts[as_i<node_type::LEAF>] > 0);
--node_counts[as_i<node_type::LEAF>];
}
template <class INode>
constexpr void increment_inode_count() noexcept;
template <class INode>
constexpr void decrement_inode_count() noexcept;
template <node_type NodeType>
constexpr void account_growing_inode() noexcept;
template <node_type NodeType>
constexpr void account_shrinking_inode() noexcept;
detail::node_ptr root{nullptr};
std::size_t current_memory_use{0};
node_type_counter_array node_counts{};
inode_type_counter_array growing_inode_counts{};
inode_type_counter_array shrinking_inode_counts{};
std::uint64_t key_prefix_splits{0};
friend auto detail::make_db_leaf_ptr<detail::node_header, db>(detail::art_key,
value_view,
db &);
template <class, class>
friend class detail::basic_db_leaf_deleter;
template <class, template <class> class, class, class, template <class> class,
template <class, class> class>
friend struct detail::basic_art_policy;
template <class, class>
friend class detail::basic_db_inode_deleter;
friend struct detail::impl_helpers;
};
} // namespace unodb
#endif // UNODB_DETAIL_ART_HPP