rippled
TaggedPointer.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
21 #define RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
22 
23 #include <ripple/shamap/SHAMapTreeNode.h>
24 
25 #include <array>
26 #include <bit>
27 #include <cstdint>
28 #include <optional>
29 
30 namespace ripple {
31 
60 {
61  static_assert(
62  alignof(SHAMapHash) >= 4,
63  "Bad alignment: Tag pointer requires low two bits to be zero.");
69  static constexpr std::uintptr_t tagMask = 3;
71  static constexpr std::uintptr_t ptrMask = ~tagMask;
72 
74  void
76 
78  {
79  };
93  explicit TaggedPointer(RawAllocateTag, std::uint8_t numChildren);
94 
95 public:
96  TaggedPointer() = delete;
97  explicit TaggedPointer(std::uint8_t numChildren);
98 
113  explicit TaggedPointer(
114  TaggedPointer&& other,
115  std::uint16_t isBranch,
116  std::uint8_t toAllocate);
117 
139  explicit TaggedPointer(
140  TaggedPointer&& other,
141  std::uint16_t srcBranches,
142  std::uint16_t dstBranches,
143  std::uint8_t toAllocate);
144 
145  TaggedPointer(TaggedPointer const&) = delete;
146 
148 
151 
152  ~TaggedPointer();
153 
155  [[nodiscard]] std::pair<std::uint8_t, void*>
156  decode() const;
157 
159  [[nodiscard]] std::uint8_t
160  capacity() const;
161 
167  [[nodiscard]] bool
168  isDense() const;
169 
173  [[nodiscard]] std::
174  tuple<std::uint8_t, SHAMapHash*, std::shared_ptr<SHAMapTreeNode>*>
175  getHashesAndChildren() const;
176 
178  [[nodiscard]] SHAMapHash*
179  getHashes() const;
180 
182  [[nodiscard]] std::shared_ptr<SHAMapTreeNode>*
183  getChildren() const;
184 
193  template <class F>
194  void
195  iterChildren(std::uint16_t isBranch, F&& f) const;
196 
206  template <class F>
207  void
208  iterNonEmptyChildIndexes(std::uint16_t isBranch, F&& f) const;
209 
219  getChildIndex(std::uint16_t isBranch, int i) const;
220 };
221 
222 [[nodiscard]] inline int
224 {
225 #if __cpp_lib_bitops
226  return std::popcount(a);
227 #elif defined(__clang__) || defined(__GNUC__)
228  return __builtin_popcount(a);
229 #else
230  // fallback to table lookup
231  static auto constexpr const tbl = []() {
233  for (int i = 0; i != 256; ++i)
234  {
235  for (int j = 0; j != 8; ++j)
236  {
237  if (i & (1 << j))
238  ret[i]++;
239  }
240  }
241  return ret;
242  }();
243  return tbl[a & 0xff] + tbl[a >> 8];
244 #endif
245 }
246 
247 } // namespace ripple
248 
249 #endif
ripple::TaggedPointer::~TaggedPointer
~TaggedPointer()
ripple::TaggedPointer::getChildIndex
std::optional< int > getChildIndex(std::uint16_t isBranch, int i) const
Get the child's index inside the hashes or children array (which may or may not be sparse).
std::shared_ptr
STL class.
ripple::popcnt16
int popcnt16(std::uint16_t a)
Definition: TaggedPointer.h:223
std::pair
ripple::TaggedPointer::tp_
std::uintptr_t tp_
Upper bits are the pointer, lowest two bits are the tag A moved-from object will have a tp_ of zero.
Definition: TaggedPointer.h:67
ripple::TaggedPointer
TaggedPointer is a combination of a pointer and a mask stored in the lowest two bits.
Definition: TaggedPointer.h:59
ripple::TaggedPointer::operator=
TaggedPointer & operator=(TaggedPointer &&)
ripple::SHAMapHash
Definition: SHAMapHash.h:32
ripple::TaggedPointer::TaggedPointer
TaggedPointer()=delete
ripple::TaggedPointer::getHashes
SHAMapHash * getHashes() const
Get the hashes array.
ripple::TaggedPointer::isDense
bool isDense() const
Check if the arrays have a dense format.
array
cstdint
ripple::TaggedPointer::decode
std::pair< std::uint8_t, void * > decode() const
Decode the tagged pointer into its tag and pointer.
std::uintptr_t
ripple::TaggedPointer::destroyHashesAndChildren
void destroyHashesAndChildren()
Deallocate memory and run destructors.
ripple::TaggedPointer::iterNonEmptyChildIndexes
void iterNonEmptyChildIndexes(std::uint16_t isBranch, F &&f) const
Call the f callback for all non-empty branches.
bit
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::TaggedPointer::RawAllocateTag
Definition: TaggedPointer.h:77
ripple::TaggedPointer::ptrMask
static constexpr std::uintptr_t ptrMask
bit-and with this mask to get the pointer bits (mask out the tag)
Definition: TaggedPointer.h:71
optional
ripple::TaggedPointer::getChildren
std::shared_ptr< SHAMapTreeNode > * getChildren() const
Get the children array.
ripple::TaggedPointer::iterChildren
void iterChildren(std::uint16_t isBranch, F &&f) const
Call the f callback for all 16 (branchFactor) branches - even if the branch is empty.
ripple::TaggedPointer::getHashesAndChildren
std::tuple< std::uint8_t, SHAMapHash *, std::shared_ptr< SHAMapTreeNode > * > getHashesAndChildren() const
Get the number of elements in each array and a pointer to the start of each array.
ripple::TaggedPointer::capacity
std::uint8_t capacity() const
Get the number of elements allocated for each array.
ripple::TaggedPointer::tagMask
static constexpr std::uintptr_t tagMask
bit-and with this mask to get the tag bits (lowest two bits)
Definition: TaggedPointer.h:69