19 #ifndef PSTORE_CORE_HAMT_MAP_HPP 20 #define PSTORE_CORE_HAMT_MAP_HPP 27 class transaction_base;
31 inline index_base::~index_base () =
default;
34 # pragma warning(push) 35 # pragma warning(disable : 4521) 37 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
49 using hash_type = details::hash_type;
58 template <
typename K,
typename V>
59 struct pair_types_compatible
60 : std::integral_constant<bool,
61 serialize::is_compatible<KeyType, K>::value &&
62 serialize::is_compatible<ValueType, V>::value> {};
65 using key_equal = KeyEqual;
66 using key_type = KeyType;
67 using mapped_type = ValueType;
68 using value_type = std::pair<KeyType const, ValueType>;
71 template <
bool IsConstIterator = true>
83 using iterator_category = std::forward_iterator_tag;
84 using value_type = hamt_map<KeyType, ValueType, Hash, KeyEqual>::value_type;
85 using difference_type = std::ptrdiff_t;
86 using pointer = value_type *;
87 using reference = value_type &;
92 typename std::conditional<IsConstIterator, value_type
const &,
98 typename std::conditional<IsConstIterator, value_type
const *,
101 using database_reference =
102 typename std::conditional<IsConstIterator, database const &, database &>::type;
106 , visited_parents_ (std::move (parents))
111 , visited_parents_ (other.visited_parents_)
112 , index_ (other.index_) {
117 , visited_parents_{std::move (other.visited_parents_)}
118 , index_{other.index_}
119 , pos_{std::move (other.pos_)} {}
123 template <
bool Enable = IsConstIterator,
124 typename =
typename std::enable_if<Enable>::type>
128 , visited_parents_ (other.visited_parents_)
129 , index_ (other.index_) {
137 assert (&db_ == &rhs.db_);
138 visited_parents_ = rhs.visited_parents_;
147 assert (&db_ == &rhs.db_);
148 visited_parents_ = std::move (rhs.visited_parents_);
150 pos_ = std::move (rhs.pos_);
156 return index_ == other.index_ && visited_parents_ == other.visited_parents_;
159 bool operator!= (
iterator_base const & other)
const {
return !operator== (other); }
164 if (pos_ ==
nullptr) {
165 pos_ = std::make_unique<value_type> (
166 index_->load_leaf_node (db_, this->get_address ()));
186 PSTORE_ASSERT (visited_parents_.size () >= 1);
188 PSTORE_ASSERT (parent.node.is_leaf () && parent.position == details::not_found);
189 return parent.node.to_address ();
193 void increment_internal_node ();
198 void move_to_left_most_child (index_pointer node);
200 unsigned get_shift_bits ()
const {
201 PSTORE_ASSERT (visited_parents_.size () >= 1);
202 return static_cast<unsigned> ((visited_parents_.size () - 1) *
203 details::hash_index_bits);
206 database_reference db_;
207 parent_stack visited_parents_;
209 mutable std::unique_ptr<value_type> pos_;
224 Hash
const & hash = Hash (), KeyEqual
const & equal = KeyEqual ());
228 ~
hamt_map ()
override { this->clear (); }
238 make_range (
database const & db)
const {
245 return make_begin_iterator (db, *
this);
247 const_iterator cbegin (
database const & db)
const {
248 return make_begin_iterator (db, *
this);
252 iterator
end (
database & db) {
return make_end_iterator (db, *
this); }
253 const_iterator
end (
database const & db)
const {
return make_end_iterator (db, *
this); }
254 const_iterator cend (
database const & db)
const {
255 return make_end_iterator (db, *
this);
265 PSTORE_ASSERT (root_.is_empty () == (size_ == 0));
270 std::size_t
size () const noexcept {
return size_; }
287 template <
typename OtherKeyType,
typename OtherValueType,
288 typename =
typename std::enable_if<
289 pair_types_compatible<OtherKeyType, OtherValueType>::value>::type>
291 std::pair<OtherKeyType, OtherValueType>
const & value)
292 -> std::pair<iterator, bool>;
307 template <
typename OtherKeyType,
typename OtherValueType,
308 typename =
typename std::enable_if<
309 pair_types_compatible<OtherKeyType, OtherValueType>::value>::type>
311 std::pair<OtherKeyType, OtherValueType>
const & value)
312 -> std::pair<iterator, bool>;
328 template <
typename OtherKeyType,
typename OtherValueType,
329 typename =
typename std::enable_if<
330 pair_types_compatible<OtherKeyType, OtherValueType>::value>::type>
332 OtherValueType
const & value) -> std::pair<iterator, bool>;
346 template <
typename OtherKeyType,
347 typename =
typename std::enable_if<
349 const_iterator
find (
database const & db, OtherKeyType
const & key)
const;
358 template <
typename OtherKeyType,
359 typename =
typename std::enable_if<
362 return this->
find (db, key) != this->
end (db);
385 static constexpr std::array<std::uint8_t, 8> index_signature{
386 {
'I',
'n',
'd',
'x',
'H',
'e',
'd',
'r'}};
389 template <
typename OtherValueType>
398 if (root_.is_heap ()) {
399 this->clear (root_, 0 );
409 template <
typename OtherValueType>
412 OtherValueType
const & new_leaf, hash_type existing_hash,
413 hash_type hash,
unsigned shifts,
433 template <
typename OtherValueType>
435 OtherValueType
const & value, hash_type hash,
437 bool is_upsert) -> std::pair<index_pointer, bool>;
439 template <
typename OtherValueType>
441 OtherValueType
const & value,
443 -> std::pair<index_pointer, bool>;
447 template <
typename OtherValueType>
449 OtherValueType
const & value, hash_type hash,
unsigned shifts,
451 -> std::pair<index_pointer, bool>;
453 template <
typename Database,
typename HamtMap,
456 static Iterator make_begin_iterator (Database && db, HamtMap && m);
457 template <
typename Database,
typename HamtMap,
460 static Iterator make_end_iterator (Database && db, HamtMap && m);
464 template <
typename OtherValueType>
466 OtherValueType
const & value,
485 static constexpr
auto internal_nodes_per_chunk =
503 std::unique_ptr<internal_nodes_container> internals_container_;
507 std::size_t size_ = 0;
514 # pragma warning(pop) 525 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
526 template <
bool IsConstIterator>
531 PSTORE_ASSERT (!visited_parents_.empty ());
532 this->increment_internal_node ();
546 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
547 template <
bool IsConstIterator>
548 void hamt_map<KeyType, ValueType, Hash,
551 visited_parents_.pop ();
553 if (!visited_parents_.empty ()) {
554 std::shared_ptr<void const> node;
559 unsigned const shifts = this->get_shift_bits ();
560 bool const is_internal_node = details::depth_is_internal_node (shifts);
561 std::size_t
size = 0;
562 if (is_internal_node) {
564 PSTORE_ASSERT (
internal !=
nullptr);
565 size =
internal->size ();
568 PSTORE_ASSERT (linear !=
nullptr);
569 size = linear->
size ();
572 PSTORE_ASSERT (!parent.node.
is_leaf () && parent.position <
size);
575 if (parent.position >= size) {
576 this->increment_internal_node ();
579 visited_parents_.top ().position = parent.position;
582 if (is_internal_node) {
583 index_pointer child = (*internal)[parent.position];
584 if (child.is_internal ()) {
585 this->move_to_left_most_child (child);
590 visited_parents_.push (
599 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
600 template <
bool IsConstIterator>
602 IsConstIterator>::move_to_left_most_child (index_pointer node) {
604 std::shared_ptr<void const> store_node;
605 while (!node.is_leaf ()) {
607 if (visited_parents_.size () <= details::max_internal_depth) {
610 PSTORE_ASSERT (!store_node || store_node.get () ==
internal);
611 node = (*internal)[0];
629 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
630 constexpr std::array<std::uint8_t, 8>
633 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
636 KeyEqual
const & equal)
637 : internals_container_{std::make_unique<internal_nodes_container> ()}
638 , revision_{db.get_current_revision ()}
644 std::shared_ptr<header_block const>
const hb = db.getro (pos);
646 #if PSTORE_SIGNATURE_CHECKS_ENABLED 647 if (hb->signature != index_signature) {
648 raise (pstore::error_code::index_corrupt);
654 if (root.is_heap () || (hb->size == 0U && !root.is_empty ()) ||
655 (hb->size > 0U && root.is_empty ()) ||
656 (hb->size == 1U && !root.is_leaf ()) ||
657 (hb->size > 1U && !root.is_internal ())) {
659 raise (pstore::error_code::index_corrupt);
669 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
673 if (details::depth_is_internal_node (shifts)) {
676 for (
auto p : *
internal) {
678 this->clear (p, shifts + details::hash_index_bits);
683 this->delete_node (node, shifts);
688 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
693 return serialize::read<std::pair<KeyType, ValueType>> (
699 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
709 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
710 template <
typename OtherValueType>
717 constexpr
auto aligned_to = std::size_t{4};
718 static_assert ((details::internal_node_bit | details::heap_node_bit) == aligned_to - 1,
719 "expected required alignment to be 4");
720 transaction.
allocate (0, aligned_to);
725 PSTORE_ASSERT ((result.absolute () & (aligned_to - 1U)) == 0U);
733 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
734 template <
typename OtherValueType>
737 OtherValueType
const & new_leaf, hash_type existing_hash, hash_type hash,
740 if (details::depth_is_internal_node (shifts)) {
741 auto const new_hash = hash & details::hash_index_mask;
742 auto const old_hash = existing_hash & details::hash_index_mask;
743 if (new_hash != old_hash) {
745 this->store_leaf_node (transaction, new_leaf, parents);
747 internal_node::allocate (internals_container_.get (), existing_leaf,
750 internal_ptr, internal_node::get_new_index (new_hash, old_hash)});
762 shifts += details::hash_index_bits;
763 hash >>= details::hash_index_bits;
764 existing_hash >>= details::hash_index_bits;
767 transaction, existing_leaf, new_leaf, existing_hash, hash, shifts, parents);
769 internal_node::allocate (internals_container_.get (), leaf_ptr, old_hash)};
776 linear_node::allocate (existing_leaf.to_address (),
777 this->store_leaf_node (transaction, new_leaf, parents))
785 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
787 unsigned const shifts) {
789 PSTORE_ASSERT (!node.
is_leaf ());
790 if (details::depth_is_internal_node (shifts)) {
802 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
803 template <
typename OtherValueType>
807 -> std::pair<index_pointer, bool> {
809 std::shared_ptr<internal_node const> iptr;
811 std::tie (iptr,
internal) = internal_node::get_node (transaction.db (), node);
812 PSTORE_ASSERT (
internal !=
nullptr);
816 auto index = std::size_t{0};
817 std::tie (child_slot, index) =
internal->lookup (hash & details::hash_index_mask);
821 if (index == details::not_found) {
823 internal_node::make_writable (internals_container_.get (), node, *
internal);
825 hash,
index_pointer{this->store_leaf_node (transaction, value, parents)},
830 shifts += details::hash_index_bits;
831 hash >>= details::hash_index_bits;
836 std::tie (new_child, key_exists) = this->insert_node (transaction, child_slot, value,
837 hash, shifts, parents, is_upsert);
843 std::unique_ptr<internal_node> new_node;
844 if (new_child != child_slot) {
846 internal_node::make_writable (internals_container_.get (), node, *
internal);
850 this->delete_node (child, shifts);
857 return {node, key_exists};
862 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
863 template <
typename OtherValueType>
867 -> std::pair<index_pointer, bool> {
870 bool key_exists =
false;
872 std::shared_ptr<linear_node const> lptr;
874 std::tie (lptr, orig_node) = linear_node::get_node (transaction.db (), node);
875 PSTORE_ASSERT (orig_node !=
nullptr);
878 auto index = std::size_t{0};
880 std::tie (child_slot, index) =
881 orig_node->
lookup<KeyType> (transaction.db (), value.first, equal_);
882 if (index == details::not_found) {
887 std::unique_ptr<linear_node> new_node = linear_node::allocate_from (*orig_node, 1U);
888 index = orig_node->
size ();
889 (*new_node)[index] = this->store_leaf_node (transaction, value, parents);
890 result = new_node.release ();
894 std::unique_ptr<linear_node> new_node;
903 new_node = linear_node::allocate_from (*orig_node, 0U);
904 lnode = new_node.get ();
907 (*lnode)[index] = this->store_leaf_node (transaction, value, parents);
919 return {result, key_exists};
924 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
925 template <
typename OtherValueType>
929 -> std::pair<index_pointer, bool> {
932 bool key_exists =
false;
934 key_type
const existing_key =
935 get_key (transaction.db (), node.to_address ());
936 if (equal_ (value.first, existing_key)) {
938 result = this->store_leaf_node (transaction, value, parents);
945 auto const existing_hash =
946 static_cast<hash_type
> ((hash_ (existing_key) >> shifts));
947 result = this->insert_into_leaf (transaction, node, value, existing_hash, hash,
952 if (details::depth_is_internal_node (shifts)) {
953 std::tie (result, key_exists) = this->insert_into_internal (
954 transaction, node, value, hash, shifts, parents, is_upsert);
956 std::tie (result, key_exists) =
957 this->insert_into_linear (transaction, node, value, parents, is_upsert);
961 return std::make_pair (result, key_exists);
966 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
967 template <
typename OtherValueType>
969 transaction_base & transaction, OtherValueType
const & value,
bool is_upsert)
970 -> std::pair<iterator, bool> {
974 raise (error_code::index_not_latest_revision);
978 if (this->empty ()) {
979 root_ = this->store_leaf_node (transaction, value, &parents);
981 return std::make_pair (iterator (db, std::move (parents),
this),
true);
985 bool key_exists =
false;
986 auto hash =
static_cast<hash_type
> (hash_ (value.first));
987 std::tie (root_, key_exists) = this->insert_node (
988 transaction, root_, value, hash, 0 , &reverse_parents, is_upsert);
989 while (!reverse_parents.
empty ()) {
990 parents.
push (reverse_parents.
top ());
991 reverse_parents.
pop ();
996 return std::make_pair (iterator (db, std::move (parents),
this), !key_exists);
1001 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1002 template <
typename OtherKeyType,
typename OtherValueType,
typename>
1004 transaction_base & transaction, std::pair<OtherKeyType, OtherValueType>
const & value)
1005 -> std::pair<iterator, bool> {
1007 return this->insert_or_upsert (transaction, value,
false );
1012 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1013 template <
typename OtherKeyType,
typename OtherValueType,
typename>
1015 transaction_base & transaction, std::pair<OtherKeyType, OtherValueType>
const & value)
1016 -> std::pair<iterator, bool> {
1018 return this->insert_or_upsert (transaction, value,
true );
1023 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1024 template <
typename OtherKeyType,
typename OtherValueType,
typename>
1026 transaction_base & transaction, OtherKeyType
const & key, OtherValueType
const & value)
1027 -> std::pair<iterator, bool> {
1029 return this->insert_or_assign (transaction, std::make_pair (key, value));
1034 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1037 unsigned const generation) {
1039 raise (error_code::index_not_latest_revision);
1044 if (!root_.is_address ()) {
1045 PSTORE_ASSERT (root_.is_internal ());
1046 root_ = root_.untag<
internal_node *> ()->flush (transaction, 0 );
1047 PSTORE_ASSERT (root_.is_address ());
1052 auto const header_addr = this->size () > 0U ? this->write_header_block (transaction)
1056 internals_container_->clear ();
1059 revision_ = generation;
1066 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1070 PSTORE_ASSERT (this->root ().is_address ());
1072 pos.first->signature = index_signature;
1073 pos.first->size = this->size ();
1074 pos.first->root = this->root ().to_address ();
1080 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1081 template <
typename OtherKeyType,
typename>
1083 OtherKeyType
const & key)
const 1086 return this->cend (db);
1089 auto hash =
static_cast<hash_type
> (hash_ (key));
1090 unsigned bit_shifts = 0;
1094 std::shared_ptr<void const> store_node;
1097 auto index = std::size_t{0};
1099 if (details::depth_is_internal_node (bit_shifts)) {
1102 std::tie (store_node,
internal) = internal_node::get_node (db, node);
1103 std::tie (child_node, index) =
1104 internal->lookup (hash & details::hash_index_mask);
1108 std::tie (store_node, linear) = linear_node::get_node (db, node);
1109 std::tie (child_node, index) = linear->
lookup<KeyType> (db, key, equal_);
1112 if (index == details::not_found) {
1113 return this->cend (db);
1119 bit_shifts += details::hash_index_bits;
1120 hash >>= details::hash_index_bits;
1123 PSTORE_ASSERT (node.
is_leaf ());
1124 key_type
const existing_key = get_key (db, node.to_address ());
1125 if (equal_ (existing_key, key)) {
1127 return const_iterator (db, std::move (parents),
this);
1129 return this->cend (db);
1134 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1135 template <
typename Database,
typename HamtMap,
typename Iterator>
1139 if (!m.root_.is_empty ()) {
1140 result.move_to_left_most_child (m.root_);
1147 template <
typename KeyType,
typename ValueType,
typename Hash,
typename KeyEqual>
1148 template <
typename Database,
typename HamtMap,
typename Iterator>
1156 #endif // PSTORE_CORE_HAMT_MAP_HPP const_iterator find(database const &db, OtherKeyType const &key) const
Finds an element with key equivalent to key.
void pop()
Remove the top element from the stack.
Definition: array_stack.hpp:105
This class provides a common base from which each of the real index types derives.
Definition: hamt_map_fwd.hpp:29
static auto get_node(database const &db, index_pointer node) -> std::pair< std::shared_ptr< internal_node const >, internal_node const *>
Return a pointer to an internal node.
Definition: hamt_map_types.cpp:285
hamt_map(database const &db, typed_address< header_block > pos=typed_address< header_block >::null(), Hash const &hash=Hash(), KeyEqual const &equal=KeyEqual())
An associative container that contains key-value pairs with unique keys.
Definition: hamt_map.hpp:634
An archive-reader which reads data from a database.
Definition: db_archive.hpp:102
bool contains(database const &db, OtherKeyType const &key) const
Checks if there is an element with key equivalent to key in the container.
Definition: hamt_map.hpp:361
Definition: address.hpp:81
typename std::conditional< IsConstIterator, value_type const &, value_type & >::type value_reference_type
For const_iterator: define value_reference_type to be a 'value_type const &' For iterator: define val...
Definition: hamt_map.hpp:93
typed_address< header_block > flush(transaction_base &transaction, unsigned generation)
Flush any modified index nodes to the store.
Definition: hamt_map.hpp:1036
auto insert(transaction_base &transaction, std::pair< OtherKeyType, OtherValueType > const &value) -> std::pair< iterator, bool >
Inserts an element into the hamt_map if the hamt_map doesn't already contain an element with an equiv...
Definition: hamt_map.hpp:1003
bool empty() const noexcept
Checks whether the container is empty.
Definition: hamt_map.hpp:264
auto index(gsl::czstring str, std::size_t pos) -> gsl::czstring
Returns a pointer to the beginning of the pos'th UTF-8 codepoint in the buffer at str or nullptr if e...
Definition: utf.cpp:49
A linear node.
Definition: hamt_map_types.hpp:298
static constexpr std::size_t size_bytes(std::size_t const num_children) noexcept
Returns the number of bytes occupied by an in-store internal node with the given number of child node...
Definition: hamt_map_types.hpp:646
std::pair< std::shared_ptr< void >, address > alloc_rw(std::size_t size, unsigned align)
Allocates sufficient space in the transaction for 'size' bytes at an alignment given by 'align' and r...
Definition: transaction.cpp:75
A class used to keep the pointer to parent node and the child slot.
Definition: hamt_map_types.hpp:264
virtual address allocate(std::uint64_t size, unsigned align)
Definition: transaction.cpp:52
Definition: transaction.hpp:191
Definition: address.hpp:231
A simple wrapper for std::array which provides the functionality of a stack, specifically a FILO (fir...
Definition: array_stack.hpp:39
iterator end(database &db)
Returns an iterator to the end of the container.
Definition: hamt_map.hpp:252
A Hash array mapped trie index type for the pstore.
Definition: hamt_map.hpp:48
auto make_writer(transaction_base &transaction) noexcept -> database_writer
A convenience function which simplifies the construction of a database_writer instance if the caller ...
Definition: db_archive.hpp:92
bool is_heap() const noexcept
Returns true if the index_pointer is pointing to a heap node, false otherwise.
Definition: hamt_map_types.hpp:215
bool is_leaf() const noexcept
Returns true if the index_pointer contains the address of a value in the store, false otherwise...
Definition: hamt_map_types.hpp:211
typename std::conditional< IsConstIterator, value_type const *, value_type * >::type value_pointer_type
For const_iterator: define value_pointer_type to be a 'value_type const *' For regular iterator: defi...
Definition: hamt_map.hpp:99
static auto get_node(database const &db, index_pointer const node) -> std::pair< std::shared_ptr< linear_node const >, linear_node const *>
Returns a pointer to a linear node which may be in-heap or in-store.
Definition: hamt_map_types.cpp:120
unsigned get_current_revision() const
Returns the generation number to which the database is synced.
Definition: database.hpp:262
iterator_base(iterator_base< false > const &other) noexcept
Copy constructor.
Definition: hamt_map.hpp:126
Provides serialization capabilities for common types.
address get_address() const
Returns the pstore address of the serialized value_type instance to which the iterator is currently p...
Definition: hamt_map.hpp:185
The begin() and end() functions for both hamt_map and hamt_set take an extra parameter – the owning ...
Definition: hamt_map_fwd.hpp:40
value_type load_leaf_node(database const &db, address addr) const
Read a leaf node from a store.
Definition: hamt_map.hpp:689
An internal trie node.
Definition: hamt_map_types.hpp:508
Definition: nonpod2.cpp:40
Definition: database.hpp:40
auto insert_or_assign(transaction_base &transaction, std::pair< OtherKeyType, OtherValueType > const &value) -> std::pair< iterator, bool >
If a key equivalent to value first already exists in the container, assigns value second to the mappe...
Definition: hamt_map.hpp:1014
std::size_t size() const noexcept
Returns the number of elements.
Definition: hamt_map.hpp:270
void insert_child(hash_type const hash, index_pointer const leaf, gsl::not_null< parent_stack *> parents)
Insert a child into the internal node (this).
Definition: hamt_map_types.cpp:300
std::size_t size() const
Returns the number of elements.
Definition: hamt_map_types.hpp:399
Inner class that describes a const_iterator and 'regular' iterator.
Definition: hamt_map.hpp:72
constexpr bool empty() const noexcept
Checks whether the stack is empty.
Definition: array_stack.hpp:63
void push(value_type const &value)
Inserts an element at the top of the container.
Definition: array_stack.hpp:93
Chunked-sequence is a sequence-container which uses a list of large blocks ("chunks") to ensure very ...
Definition: chunked_sequence.hpp:60
auto lookup(database const &db, OtherKeyType const &key, KeyEqual equal) const -> std::pair< index_pointer const, std::size_t >
Search the linear node and return the child slot if the key exists.
Definition: hamt_map_types.hpp:483
iterator begin(database &db)
Returns an iterator to the beginning of the container.
Definition: hamt_map.hpp:243
If the two types T1 and T2 have a compatible representation when serialized, provides the member cons...
Definition: types.hpp:321
reference top() noexcept
Acceses the top element.
Definition: array_stack.hpp:78
index_pointer root() const noexcept
Returns the index root pointer.
Definition: hamt_map.hpp:381
Types used by the HAMT index.
An index pointer is either a database address or a pointer to volatile RAM.
Definition: hamt_map_types.hpp:132
typename std::conditional< std::is_const< typename std::remove_reference< T >::type >::value, RC, R >::type type
If T is const, R const otherwise R.
Definition: inherit_const.hpp:112
The database transaction class.
Definition: transaction.hpp:43