1919#ifndef LIBBITCOIN_DATABASE_PRIMITIVES_ARRAYHEAD_HPP
2020#define LIBBITCOIN_DATABASE_PRIMITIVES_ARRAYHEAD_HPP
2121
22+ #include < atomic>
2223#include < shared_mutex>
2324#include < bitcoin/system.hpp>
2425#include < bitcoin/database/define.hpp>
@@ -29,7 +30,7 @@ namespace database {
2930
3031// / Dynamically expanding array map header.
3132// / Less efficient than a fixed-size header.
32- template <typename Link>
33+ template <typename Link, bool Align >
3334class arrayhead
3435{
3536public:
@@ -63,42 +64,45 @@ class arrayhead
6364 // / Convert natural key to head bucket index (unvalidated).
6465 inline Link index (size_t key) const NOEXCEPT;
6566
66- // / Convert natural key to head bucket index (unvalidated).
67- inline Link putter_index (size_t key) const NOEXCEPT;
68-
6967 // / Unsafe if verify false.
7068 Link at (size_t key) const NOEXCEPT;
7169
72- // / Assign value to bucket index.
73- bool push (const bytes& current , const Link& index) NOEXCEPT;
70+ // / Assign link value to bucket index.
71+ bool push (const Link& link , const Link& index) NOEXCEPT;
7472
7573private:
74+ using integer = Link::integer;
75+ static_assert (std::atomic<integer>::is_always_lock_free);
76+ static constexpr auto size_ = Align ? sizeof (integer) : Link::size;
77+
78+ // Body does not use padded link size.
7679 using body = manager<Link, system::data_array<zero>, Link::size>;
7780
7881 template <size_t Bytes>
79- static inline auto & array_cast (memory::iterator buffer ) NOEXCEPT
82+ static inline auto & to_array (memory::iterator it ) NOEXCEPT
8083 {
81- return system::unsafe_array_cast<uint8_t , Bytes>(buffer );
84+ return system::unsafe_array_cast<uint8_t , Bytes>(it );
8285 }
8386
8487 static constexpr Link position_to_link (size_t position) NOEXCEPT
8588 {
8689 using namespace system ;
87- static_assert (is_nonzero (Link::size ));
88- const auto link = floored_subtract (position / Link::size , one);
89- return possible_narrow_cast<typename Link:: integer>(link);
90+ static_assert (is_nonzero (size_ ));
91+ const auto link = floored_subtract (position / size_ , one);
92+ return possible_narrow_cast<integer>(link);
9093 }
9194
9295 // Byte offset of bucket index within head file.
9396 // [body_size][[bucket[0]...bucket[buckets-1]]]
9497 static constexpr size_t link_to_position (const Link& index) NOEXCEPT
9598 {
9699 using namespace system ;
97- BC_ASSERT (!is_multiply_overflow<size_t >(index, Link::size ));
98- BC_ASSERT (!is_add_overflow (Link::size , index * Link::size ));
99- return possible_narrow_cast<size_t >(Link::size + index * Link::size );
100+ BC_ASSERT (!is_multiply_overflow<size_t >(index, size_ ));
101+ BC_ASSERT (!is_add_overflow (size_ , index * size_ ));
102+ return possible_narrow_cast<size_t >(size_ + index * size_ );
100103 }
101104
105+ // These are thread safe.
102106 storage& file_;
103107 const Link initial_buckets_;
104108 mutable std::shared_mutex mutex_{};
@@ -107,8 +111,8 @@ class arrayhead
107111} // namespace database
108112} // namespace libbitcoin
109113
110- #define TEMPLATE template <typename Link>
111- #define CLASS arrayhead<Link>
114+ #define TEMPLATE template <typename Link, bool Align >
115+ #define CLASS arrayhead<Link, Align >
112116
113117#include < bitcoin/database/impl/primitives/arrayhead.ipp>
114118
0 commit comments