Skip to content

Commit 1d294ee

Browse files
committed
Refactor sieve as non-state-maintaining.
1 parent 4568b1d commit 1d294ee

11 files changed

Lines changed: 991 additions & 902 deletions

File tree

include/bitcoin/database/impl/primitives/hashhead.ipp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ TEMPLATE
115115
inline Link CLASS::index(const Key& key) const NOEXCEPT
116116
{
117117
using namespace system;
118-
const auto index = possible_narrow_cast<link>(keys::hash<Key>(key));
118+
const auto index = possible_narrow_cast<link>(keys::hash(key));
119119
return bit_and<link>(mask_, index);
120120
}
121121

@@ -149,9 +149,10 @@ TEMPLATE
149149
inline bool CLASS::push(bool& collision, const Link& current, bytes& next,
150150
const Key& key) NOEXCEPT
151151
{
152+
// TODO: need independent error sentinel.
152153
const auto previous = set_cell(next, current, key);
153-
if (previous == terminal)
154-
return false;
154+
////if (previous == terminal)
155+
//// return false;
155156

156157
// Conflict (body) search is bypassed by filter when key is not screened.
157158
// If collision false it is assured that table does not contain the key.
@@ -178,7 +179,7 @@ inline CLASS::cell CLASS::get_cell(const Link& index) const NOEXCEPT
178179
////const std::atomic_ref<cell> top(unsafe_byte_cast<cell>(raw));
179180
const auto& top = *pointer_cast<std::atomic<cell>>(raw);
180181

181-
// Acquire is necessary to synchronize with push release.
182+
// Acquire is necessary to synchronize with set_cell release.
182183
// Relaxed would miss next updates, so acquire is optimal.
183184
return top.load(std::memory_order_acquire);
184185
}
@@ -213,16 +214,18 @@ inline CLASS::cell CLASS::set_cell(bytes& next, const Link& current,
213214
auto head = top.load(std::memory_order_acquire);
214215
do
215216
{
217+
next = link_array(head);
218+
216219
// Compiler could order this after top.store, which would expose key
217220
// to search before next entry is linked. Thread fence imposes order.
218221
// A release fence ensures that all prior writes (like next) are
219222
// completed before any subsequent atomic store.
220-
next = link_array(head);
221223
std::atomic_thread_fence(std::memory_order_release);
222224
}
223-
while (!top.compare_exchange_weak(head,
224-
to_cell(head, current, key),
225+
while (!top.compare_exchange_weak(head, to_cell(head, current, key),
225226
std::memory_order_release, std::memory_order_acquire));
227+
228+
return top;
226229
}
227230
else
228231
{
@@ -235,9 +238,9 @@ inline CLASS::cell CLASS::set_cell(bytes& next, const Link& current,
235238
auto bytes = to_cell(top, current, key);
236239
head = cell_array(bytes);
237240
mutex_.unlock();
238-
}
239241

240-
return true;
242+
return top;
243+
}
241244
}
242245

243246
// protected
@@ -247,21 +250,21 @@ inline CLASS::cell CLASS::set_cell(bytes& next, const Link& current,
247250
TEMPLATE
248251
INLINE constexpr bool CLASS::screened(cell value, const Key& key) NOEXCEPT
249252
{
250-
if constexpr (sieve_filter::disabled)
253+
if constexpr (sieve_t::disabled)
251254
{
252255
return true;
253256
}
254257
else
255258
{
256-
return sieve_filter{ to_filter(value) }.screened(fingerprint(key));
259+
return sieve_t::is_screened(to_filter(value), fingerprint(key));
257260
}
258261
}
259262

260263
TEMPLATE
261264
INLINE constexpr CLASS::filter CLASS::fingerprint(const Key& key) NOEXCEPT
262265
{
263266
using namespace system;
264-
return possible_narrow_cast<filter>(keys::thumb<Key>(key));
267+
return possible_narrow_cast<filter>(keys::thumb(key));
265268
}
266269

267270
TEMPLATE
@@ -274,7 +277,7 @@ INLINE constexpr CLASS::filter CLASS::to_filter(cell value) NOEXCEPT
274277
TEMPLATE
275278
INLINE constexpr CLASS::link CLASS::to_link(cell value) NOEXCEPT
276279
{
277-
if constexpr (sieve_filter::disabled)
280+
if constexpr (sieve_t::disabled)
278281
{
279282
return system::possible_narrow_cast<link>(value);
280283
}
@@ -293,18 +296,15 @@ TEMPLATE
293296
INLINE constexpr CLASS::cell CLASS::to_cell(cell previous, link current,
294297
const Key& key) NOEXCEPT
295298
{
296-
if constexpr (sieve_filter::disabled)
299+
if constexpr (sieve_t::disabled)
297300
{
298301
return current;
299302
}
300303
else
301304
{
302305
using namespace system;
303-
static_assert(sizeof(filter) <= sizeof(cell));
304-
sieve_filter filter{ to_filter(previous) };
305-
filter.screen(fingerprint(key));
306-
const auto shifted = shift_left<cell>(filter.value(), link_bits);
307-
return bit_or<cell>(shifted, current);
306+
const auto value = sieve_t::screen(to_filter(previous), fingerprint(key));
307+
return bit_or<cell>(shift_left<cell>(value, link_bits), current);
308308
}
309309
}
310310

include/bitcoin/database/impl/primitives/hashmap.ipp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,10 @@ inline bool CLASS::put(bool& duplicate, const memory_ptr& ptr,
377377
if (!write(previous_head, ptr, link, key, element))
378378
return false;
379379

380-
if (!previous_head.is_terminal())
381-
counter_.fetch_add(one, std::memory_order_relaxed);
380+
if (previous_head.is_terminal())
381+
ncounter_.fetch_add(one, std::memory_order_relaxed);
382+
else
383+
pcounter_.fetch_add(one, std::memory_order_relaxed);
382384

383385
duplicate = !first(ptr, previous_head, key).is_terminal();
384386
return true;

0 commit comments

Comments
 (0)