xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
include
xrpl
shamap
SHAMapItem.h
1
#pragma once
2
3
#include <xrpl/basics/ByteUtilities.h>
4
#include <xrpl/basics/CountedObject.h>
5
#include <xrpl/basics/SlabAllocator.h>
6
#include <xrpl/basics/Slice.h>
7
#include <xrpl/basics/base_uint.h>
8
#include <xrpl/basics/contract.h>
9
#include <xrpl/beast/utility/instrumentation.h>
10
11
#include <boost/smart_ptr/intrusive_ptr.hpp>
12
13
#include <
atomic
>
14
#include <
cstddef
>
15
#include <
cstdint
>
16
#include <
cstring
>
17
#include <
memory
>
18
#include <
type_traits
>
19
20
namespace
xrpl
{
21
22
// an item stored in a SHAMap
23
class
SHAMapItem
:
public
CountedObject
<SHAMapItem>
24
{
25
// These are used to support boost::intrusive_ptr reference counting
26
// These functions are used internally by boost::intrusive_ptr to handle
27
// lifetime management.
28
friend
void
29
intrusive_ptr_add_ref
(
SHAMapItem
const
* x);
30
31
friend
void
32
intrusive_ptr_release
(
SHAMapItem
const
* x);
33
34
// This is the interface for creating new instances of this class.
35
friend
boost::intrusive_ptr<SHAMapItem>
36
makeShamapitem
(
UInt256
const
& tag,
Slice
data
);
37
38
private
:
39
UInt256
const
tag_
;
40
41
// We use std::uint32_t to minimize the size; there's no SHAMapItem whose
42
// size exceeds 4GB and there won't ever be (famous last words?), so this
43
// is safe.
44
std::uint32_t
const
size_
;
45
46
// This is the reference count used to support boost::intrusive_ptr
47
mutable
std::atomic<std::uint32_t>
refcount_
= 1;
48
49
// Because of the unusual way in which SHAMapItem objects are constructed
50
// the only way to properly create one is to first allocate enough memory
51
// so we limit this constructor to codepaths that do this right and limit
52
// arbitrary construction.
53
SHAMapItem
(
UInt256
const
& tag,
Slice
data
)
54
:
tag_
(tag),
size_
(static_cast<
std
::uint32_t>(
data
.
size
()))
55
{
56
std::memcpy
(
57
reinterpret_cast<
std::uint8_t
*
>
(
this
) +
sizeof
(*
this
),
data
.data(),
data
.size());
58
}
59
60
public
:
61
SHAMapItem
() =
delete
;
62
63
SHAMapItem
(
SHAMapItem
const
& other) =
delete
;
64
65
SHAMapItem
&
66
operator=
(
SHAMapItem
const
& other) =
delete
;
67
68
SHAMapItem
(
SHAMapItem
&& other) =
delete
;
69
70
SHAMapItem
&
71
operator=
(
SHAMapItem
&&) =
delete
;
72
73
UInt256
const
&
74
key
()
const
75
{
76
return
tag_
;
77
}
78
79
std::size_t
80
size
()
const
81
{
82
return
size_
;
83
}
84
85
void
const
*
86
data
()
const
87
{
88
return
reinterpret_cast<
std::uint8_t
const*
>
(
this
) +
sizeof
(*
this
);
89
}
90
91
Slice
92
slice
()
const
93
{
94
return
{
data
(),
size
()};
95
}
96
};
97
98
namespace
detail {
99
100
// clang-format off
101
// The slab cutoffs and the number of megabytes per allocation are customized
102
// based on the number of objects of each size we expect to need at any point
103
// in time and with an eye to minimize the number of slack bytes in a block.
104
inline
SlabAllocatorSet<SHAMapItem>
gSlabber
({
105
{ 128,
megabytes
(
std::size_t
(60)) },
106
{ 192,
megabytes
(
std::size_t
(46)) },
107
{ 272,
megabytes
(
std::size_t
(60)) },
108
{ 384,
megabytes
(
std::size_t
(56)) },
109
{ 564,
megabytes
(
std::size_t
(40)) },
110
{ 772,
megabytes
(
std::size_t
(46)) },
111
{ 1052,
megabytes
(
std::size_t
(60)) },
112
});
113
// clang-format on
114
115
}
// namespace detail
116
117
inline
void
118
intrusive_ptr_add_ref
(
SHAMapItem
const
* x)
119
{
120
// This can only happen if someone releases the last reference to the
121
// item while we were trying to increment the refcount.
122
if
(x->
refcount_
++ == 0)
123
logicError
(
"SHAMapItem: the reference count is 0!"
);
124
}
125
126
inline
void
127
intrusive_ptr_release
(
SHAMapItem
const
* x)
128
{
129
if
(--x->
refcount_
== 0)
130
{
131
auto
p =
reinterpret_cast<
std::uint8_t
const*
>
(x);
132
133
// The SHAMapItem constructor isn't trivial (because the destructor
134
// for CountedObject isn't) so we can't avoid calling it here, but
135
// plan for a future where we might not need to.
136
if
constexpr
(!
std::is_trivially_destructible_v<SHAMapItem>
)
137
std::destroy_at
(x);
138
139
// If the slabber doesn't claim this pointer, it was allocated
140
// manually, so we free it manually.
141
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
142
if
(!
detail::gSlabber
.deallocate(
const_cast<
std::uint8_t
*
>
(p)))
143
delete
[] p;
144
}
145
}
146
147
inline
boost::intrusive_ptr<SHAMapItem>
148
makeShamapitem
(
UInt256
const
& tag,
Slice
data
)
149
{
150
XRPL_ASSERT(
151
data
.size() <=
megabytes<std::size_t>
(16),
"xrpl::makeShamapitem : maximum input size"
);
152
153
// NOLINTNEXTLINE(misc-const-correctness)
154
std::uint8_t
* raw =
detail::gSlabber
.allocate(
data
.size());
155
156
// If we can't grab memory from the slab allocators, we fall back to
157
// the standard library and try to grab a precisely-sized memory block:
158
if
(raw ==
nullptr
)
159
raw =
new
std::uint8_t
[
sizeof
(
SHAMapItem
) +
data
.size()];
160
161
// We do not increment the reference count here on purpose: the
162
// constructor of SHAMapItem explicitly sets it to 1. We use the fact
163
// that the refcount can never be zero before incrementing as an
164
// invariant.
165
return
{
new
(raw)
SHAMapItem
{tag,
data
},
false
};
166
}
167
168
static_assert
(
alignof
(
SHAMapItem
) != 40);
169
static_assert
(
alignof
(
SHAMapItem
) == 8 ||
alignof
(
SHAMapItem
) == 4);
170
171
inline
boost::intrusive_ptr<SHAMapItem>
172
makeShamapitem
(
SHAMapItem
const
& other)
173
{
174
return
makeShamapitem
(other.
key
(), other.
slice
());
175
}
176
177
}
// namespace xrpl
atomic
xrpl::CountedObject< SHAMapItem >::CountedObject
CountedObject() noexcept
Definition
CountedObject.h:119
xrpl::SHAMapItem
Definition
SHAMapItem.h:24
xrpl::SHAMapItem::makeShamapitem
friend boost::intrusive_ptr< SHAMapItem > makeShamapitem(UInt256 const &tag, Slice data)
Definition
SHAMapItem.h:148
xrpl::SHAMapItem::operator=
SHAMapItem & operator=(SHAMapItem const &other)=delete
xrpl::SHAMapItem::SHAMapItem
SHAMapItem(SHAMapItem &&other)=delete
xrpl::SHAMapItem::SHAMapItem
SHAMapItem()=delete
xrpl::SHAMapItem::size_
std::uint32_t const size_
Definition
SHAMapItem.h:44
xrpl::SHAMapItem::intrusive_ptr_add_ref
friend void intrusive_ptr_add_ref(SHAMapItem const *x)
Definition
SHAMapItem.h:118
xrpl::SHAMapItem::SHAMapItem
SHAMapItem(SHAMapItem const &other)=delete
xrpl::SHAMapItem::SHAMapItem
SHAMapItem(UInt256 const &tag, Slice data)
Definition
SHAMapItem.h:53
xrpl::SHAMapItem::size
std::size_t size() const
Definition
SHAMapItem.h:80
xrpl::SHAMapItem::key
UInt256 const & key() const
Definition
SHAMapItem.h:74
xrpl::SHAMapItem::intrusive_ptr_release
friend void intrusive_ptr_release(SHAMapItem const *x)
Definition
SHAMapItem.h:127
xrpl::SHAMapItem::slice
Slice slice() const
Definition
SHAMapItem.h:92
xrpl::SHAMapItem::data
void const * data() const
Definition
SHAMapItem.h:86
xrpl::SHAMapItem::tag_
UInt256 const tag_
Definition
SHAMapItem.h:39
xrpl::SHAMapItem::refcount_
std::atomic< std::uint32_t > refcount_
Definition
SHAMapItem.h:47
xrpl::SHAMapItem::operator=
SHAMapItem & operator=(SHAMapItem &&)=delete
xrpl::SlabAllocatorSet
A collection of slab allocators of various sizes for a given type.
Definition
SlabAllocator.h:296
xrpl::Slice
An immutable linear range of bytes.
Definition
Slice.h:28
cstddef
cstdint
cstring
std::destroy_at
T destroy_at(T... args)
std::uint32_t
std::is_trivially_destructible_v
T is_trivially_destructible_v
std::memcpy
T memcpy(T... args)
memory
std
STL namespace.
xrpl::detail::gSlabber
SlabAllocatorSet< SHAMapItem > gSlabber({ { 128, megabytes(std::size_t(60)) }, { 192, megabytes(std::size_t(46)) }, { 272, megabytes(std::size_t(60)) }, { 384, megabytes(std::size_t(56)) }, { 564, megabytes(std::size_t(40)) }, { 772, megabytes(std::size_t(46)) }, { 1052, megabytes(std::size_t(60)) }, })
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::intrusive_ptr_release
void intrusive_ptr_release(SHAMapItem const *x)
Definition
SHAMapItem.h:127
xrpl::intrusive_ptr_add_ref
void intrusive_ptr_add_ref(SHAMapItem const *x)
Definition
SHAMapItem.h:118
xrpl::logicError
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition
libxrpl/basics/contract.cpp:19
xrpl::UInt256
BaseUInt< 256 > UInt256
Definition
base_uint.h:580
xrpl::makeShamapitem
boost::intrusive_ptr< SHAMapItem > makeShamapitem(UInt256 const &tag, Slice data)
Definition
SHAMapItem.h:148
xrpl::megabytes
constexpr auto megabytes(T value) noexcept
Definition
ByteUtilities.h:14
std::size_t
type_traits
Generated by
1.17.0