PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
segment_vector.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2019-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_SEGMENT_VECTOR_HPP
10 #define LIBPMEMOBJ_SEGMENT_VECTOR_HPP
11 
21 #include <libpmemobj++/pext.hpp>
23 #include <libpmemobj++/utils.hpp>
24 
25 #include <vector>
26 
27 namespace pmem
28 {
29 namespace obj
30 {
31 
35 namespace segment_vector_internal
36 {
45 template <typename Container, bool is_const>
47 public:
48  /* Traits */
49  using iterator_category = std::random_access_iterator_tag;
50  using difference_type = std::ptrdiff_t;
51  using table_type = Container;
52  using size_type = typename table_type::size_type;
53  using value_type = typename table_type::value_type;
54  /* Constant dependent traits */
55  using table_ptr =
56  typename std::conditional<is_const, const table_type *,
57  table_type *>::type;
58  using reference =
59  typename std::conditional<is_const,
60  typename table_type::const_reference,
61  typename table_type::reference>::type;
62  using pointer =
63  typename std::conditional<is_const,
64  typename table_type::const_pointer,
65  typename table_type::pointer>::type;
66 
67  /* To implement methods where operands differ in constancy */
68  friend class segment_iterator<Container, true>;
69  friend class segment_iterator<Container, false>;
70 
71 private:
72  /* Pointer to container for iteration */
73  table_ptr table;
74  /* Index of element in the container */
75  size_type index;
76 
77 public:
78  /* Сonstructors */
79  segment_iterator() noexcept;
80  explicit segment_iterator(table_ptr tab, size_type idx) noexcept;
81  segment_iterator(const segment_iterator &other);
82 
83  /* Copy ctor to enable conversion from non-const to const
84  * iterator */
85  template <typename U = void,
86  typename = typename std::enable_if<is_const, U>::type>
88 
89  /* In(de)crement methods */
92  segment_iterator operator+(difference_type idx) const;
93  segment_iterator &operator+=(difference_type idx);
96  segment_iterator operator-(difference_type idx) const;
97  segment_iterator &operator-=(difference_type idx);
98  template <bool C>
99  difference_type
100  operator+(const segment_iterator<Container, C> &rhs) const;
101  template <bool C>
102  difference_type
103  operator-(const segment_iterator<Container, C> &rhs) const;
104 
110  template <bool C>
111  bool operator==(const segment_iterator<Container, C> &rhs) const;
112  template <bool C>
113  bool operator!=(const segment_iterator<Container, C> &rhs) const;
114  template <bool C>
115  bool operator<(const segment_iterator<Container, C> &rhs) const;
116  template <bool C>
117  bool operator>(const segment_iterator<Container, C> &rhs) const;
118  template <bool C>
119  bool operator<=(const segment_iterator<Container, C> &rhs) const;
120  template <bool C>
121  bool operator>=(const segment_iterator<Container, C> &rhs) const;
122 
123  /* Access methods */
124  reference operator*() const;
125  pointer operator->() const;
126 };
127 
131 template <typename Container, bool is_const>
133  : table(nullptr), index()
134 {
135 }
136 
141 template <typename Container, bool is_const>
143  size_type idx) noexcept
144  : table(tab), index(idx)
145 {
146 }
147 
152 template <typename Container, bool is_const>
154  const segment_iterator &other)
155  : table(other.table), index(other.index)
156 {
157 }
158 
160 template <typename Container, bool is_const>
161 template <typename U, typename>
164  : table(other.table), index(other.index)
165 {
166 }
167 
173 template <typename Container, bool is_const>
176 {
177  ++index;
178  return *this;
179 }
180 
186 template <typename Container, bool is_const>
189 {
190  auto iterator = *this;
191  ++*this;
192  return iterator;
193 }
194 
200 template <typename Container, bool is_const>
203 {
204  return segment_iterator(table, index + static_cast<size_type>(idx));
205 }
206 
212 template <typename Container, bool is_const>
215 {
216  index += static_cast<size_type>(idx);
217  return *this;
218 }
219 
225 template <typename Container, bool is_const>
228 {
229  --index;
230  return *this;
231 }
232 
238 template <typename Container, bool is_const>
241 {
242  auto iterator = *this;
243  --*this;
244  return iterator;
245 }
246 
252 template <typename Container, bool is_const>
255 {
256  return segment_iterator(table, index - static_cast<size_type>(idx));
257 }
258 
264 template <typename Container, bool is_const>
267 {
268  index -= static_cast<size_type>(idx);
269  return *this;
270 }
271 
277 template <typename Container, bool is_const>
278 template <bool C>
279 typename segment_iterator<Container, is_const>::difference_type
281  const segment_iterator<Container, C> &rhs) const
282 {
283  return static_cast<difference_type>(index + rhs.index);
284 }
285 
291 template <typename Container, bool is_const>
292 template <bool C>
293 typename segment_iterator<Container, is_const>::difference_type
295  const segment_iterator<Container, C> &rhs) const
296 {
297  return static_cast<difference_type>(index - rhs.index);
298 }
299 
307 template <typename Container, bool is_const>
308 template <bool C>
309 bool
311  const segment_iterator<Container, C> &rhs) const
312 {
313  return (table == rhs.table) && (index == rhs.index);
314 }
315 
324 template <typename Container, bool is_const>
325 template <bool C>
326 bool
328  const segment_iterator<Container, C> &rhs) const
329 {
330  return (table != rhs.table) || (index != rhs.index);
331 }
332 
343 template <typename Container, bool is_const>
344 template <bool C>
345 bool
347  const segment_iterator<Container, C> &rhs) const
348 {
349  if (table != rhs.table)
350  throw std::invalid_argument("segment_iterator::operator<");
351 
352  return index < rhs.index;
353 }
354 
366 template <typename Container, bool is_const>
367 template <bool C>
368 bool
370  const segment_iterator<Container, C> &rhs) const
371 {
372  if (table != rhs.table)
373  throw std::invalid_argument("segment_iterator::operator>");
374 
375  return index > rhs.index;
376 }
377 
389 template <typename Container, bool is_const>
390 template <bool C>
391 bool
393  const segment_iterator<Container, C> &rhs) const
394 {
395  if (table != rhs.table)
396  throw std::invalid_argument("segment_iterator::operator<=");
397 
398  return index <= rhs.index;
399 }
400 
412 template <typename Container, bool is_const>
413 template <bool C>
414 bool
416  const segment_iterator<Container, C> &rhs) const
417 {
418  if (table != rhs.table)
419  throw std::invalid_argument("segment_iterator::operator>=");
420 
421  return index >= rhs.index;
422 }
423 
427 template <typename Container, bool is_const>
428 typename segment_iterator<Container, is_const>::reference
430 {
431  return table->operator[](index);
432 }
433 
437 template <typename Container, bool is_const>
438 typename segment_iterator<Container, is_const>::pointer
440 {
441  return &operator*();
442 }
443 
444 } /* segment_vector_internal namespace */
445 
454 template <template <typename> class SegmentType = pmem::obj::vector>
456  segment_vector_internal::exponential_size_policy<
457  segment_vector_internal::array_64, SegmentType>;
458 
467 template <size_t SegmentSize = 1024,
468  template <typename> class SegmentType = pmem::obj::vector>
470  segment_vector_internal::fixed_size_policy<pmem::obj::vector,
471  SegmentType, SegmentSize>;
472 
481 template <template <typename> class SegmentType = pmem::obj::vector>
483  segment_vector_internal::exponential_size_policy<pmem::obj::vector,
484  SegmentType>;
485 
505 template <typename T, typename Policy = exponential_size_vector_policy<>>
507 public:
508  /* Specific traits*/
509  using policy_type = Policy;
510  using segment_type = typename policy_type::template segment_type<T>;
511  using segment_vector_type =
512  typename policy_type::template segment_vector_type<T>;
513  /* Simple access to methods */
514  using policy = policy_type;
515  using storage = policy_type;
516 
517  /* Traits */
518  using value_type = T;
519  using size_type = std::size_t;
520  using difference_type = std::ptrdiff_t;
521  using reference = value_type &;
522  using const_reference = const value_type &;
523  using pointer = value_type *;
524  using const_pointer = const value_type *;
525  using iterator =
527  false>;
528  using const_iterator =
530  using reverse_iterator = std::reverse_iterator<iterator>;
531  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
532 
533  /* Constructors */
534  segment_vector();
535  segment_vector(size_type count, const value_type &value);
536  explicit segment_vector(size_type count);
537  template <typename InputIt,
538  typename std::enable_if<
540  InputIt>::type * = nullptr>
541  segment_vector(InputIt first, InputIt last);
542  segment_vector(const segment_vector &other);
544  segment_vector(std::initializer_list<T> init);
545  segment_vector(const std::vector<T> &other);
546 
547  /* Assign operators */
548  segment_vector &operator=(const segment_vector &other);
550  segment_vector &operator=(std::initializer_list<T> ilist);
551  segment_vector &operator=(const std::vector<T> &other);
552 
553  /* Assign methods */
554  void assign(size_type count, const_reference value);
555  template <typename InputIt,
556  typename std::enable_if<
558  InputIt>::type * = nullptr>
559  void assign(InputIt first, InputIt last);
560  void assign(std::initializer_list<T> ilist);
561  void assign(const segment_vector &other);
562  void assign(segment_vector &&other);
563  void assign(const std::vector<T> &other);
564 
565  /* Destructor */
566  ~segment_vector();
567 
568  /* Element access */
569  reference at(size_type n);
570  const_reference at(size_type n) const;
571  const_reference const_at(size_type n) const;
572  reference operator[](size_type n);
573  const_reference operator[](size_type n) const;
574  reference front();
575  const_reference front() const;
576  const_reference cfront() const;
577  reference back();
578  const_reference back() const;
579  const_reference cback() const;
580 
581  /* Iterators */
582  iterator begin();
583  const_iterator begin() const noexcept;
584  const_iterator cbegin() const noexcept;
585  iterator end();
586  const_iterator end() const noexcept;
587  const_iterator cend() const noexcept;
588  reverse_iterator rbegin();
589  const_reverse_iterator rbegin() const noexcept;
590  const_reverse_iterator crbegin() const noexcept;
591  reverse_iterator rend();
592  const_reverse_iterator rend() const noexcept;
593  const_reverse_iterator crend() const noexcept;
594 
595  /* Range */
596  slice<iterator> range(size_type start, size_type n);
597  slice<const_iterator> range(size_type start, size_type n) const;
598  slice<const_iterator> crange(size_type start, size_type n) const;
599 
600  /* Capacity */
601  constexpr bool empty() const noexcept;
602  size_type size() const noexcept;
603  constexpr size_type max_size() const noexcept;
604  void reserve(size_type capacity_new);
605  size_type capacity() const noexcept;
606  void shrink_to_fit();
607 
608  /* Modifiers */
609  void clear();
610  void free_data();
611  iterator insert(const_iterator pos, const T &value);
612  iterator insert(const_iterator pos, T &&value);
613  iterator insert(const_iterator pos, size_type count, const T &value);
614  template <typename InputIt,
615  typename std::enable_if<
617  InputIt>::type * = nullptr>
618  iterator insert(const_iterator pos, InputIt first, InputIt last);
619  iterator insert(const_iterator pos, std::initializer_list<T> ilist);
620  template <class... Args>
621  iterator emplace(const_iterator pos, Args &&... args);
622  template <class... Args>
623  reference emplace_back(Args &&... args);
626  void push_back(const T &value);
627  void push_back(T &&value);
628  void pop_back();
629  void resize(size_type count);
630  void resize(size_type count, const value_type &value);
631  void swap(segment_vector &other);
632 
633 private:
634  /* Helper functions */
635  void internal_reserve(size_type new_capacity);
636  template <typename... Args>
637  void construct(size_type idx, size_type count, Args &&... args);
638  template <typename InputIt,
639  typename std::enable_if<
641  InputIt>::type * = nullptr>
642  void construct_range(size_type idx, InputIt first, InputIt last);
643  void insert_gap(size_type idx, size_type count);
644  void shrink(size_type size_new);
645  pool_base get_pool() const;
646  void snapshot_data(size_type idx_first, size_type idx_last);
647 
648  /* Data structure specific helper functions */
649  reference get(size_type n);
650  const_reference get(size_type n) const;
651  const_reference cget(size_type n) const;
652  bool segment_capacity_validation() const;
653 
654  /* Number of segments that are currently enabled */
655  p<size_type> _segments_used = 0;
656  /* Segments storage */
657  segment_vector_type _data;
658 };
659 
660 /* Non-member swap
661  * @relates segment_vector
662  */
663 template <typename T, typename Policy>
665 
666 /*
667  * Comparison operators between
668  * pmem::obj::experimental::segment_vector<T, Policy> and
669  * pmem::obj::experimental::segment_vector<T, Policy>
670  */
671 template <typename T, typename Policy>
672 bool operator==(const segment_vector<T, Policy> &lhs,
673  const segment_vector<T, Policy> &rhs);
674 template <typename T, typename Policy>
675 bool operator!=(const segment_vector<T, Policy> &lhs,
676  const segment_vector<T, Policy> &rhs);
677 template <typename T, typename Policy>
678 bool operator<(const segment_vector<T, Policy> &lhs,
679  const segment_vector<T, Policy> &rhs);
680 template <typename T, typename Policy>
681 bool operator<=(const segment_vector<T, Policy> &lhs,
682  const segment_vector<T, Policy> &rhs);
683 template <typename T, typename Policy>
684 bool operator>(const segment_vector<T, Policy> &lhs,
685  const segment_vector<T, Policy> &rhs);
686 template <typename T, typename Policy>
687 bool operator>=(const segment_vector<T, Policy> &lhs,
688  const segment_vector<T, Policy> &rhs);
689 
690 /*
691  * Comparison operators between
692  * pmem::obj::experimental::segment_vector<T, Policy> and
693  * std::vector<T>
694  */
695 template <typename T, typename Policy>
696 bool operator==(const segment_vector<T, Policy> &lhs,
697  const std::vector<T> &rhs);
698 template <typename T, typename Policy>
699 bool operator!=(const segment_vector<T, Policy> &lhs,
700  const std::vector<T> &rhs);
701 template <typename T, typename Policy>
702 bool operator<(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs);
703 template <typename T, typename Policy>
704 bool operator<=(const segment_vector<T, Policy> &lhs,
705  const std::vector<T> &rhs);
706 template <typename T, typename Policy>
707 bool operator>(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs);
708 template <typename T, typename Policy>
709 bool operator>=(const segment_vector<T, Policy> &lhs,
710  const std::vector<T> &rhs);
711 
712 /*
713  * Comparison operators between std::vector<T> and
714  * pmem::obj::experimental::segment_vector<T, Policy>
715  */
716 template <typename T, typename Policy>
717 bool operator==(const std::vector<T> &lhs,
718  const segment_vector<T, Policy> &rhs);
719 template <typename T, typename Policy>
720 bool operator!=(const std::vector<T> &lhs,
721  const segment_vector<T, Policy> &rhs);
722 template <typename T, typename Policy>
723 bool operator<(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs);
724 template <typename T, typename Policy>
725 bool operator<=(const std::vector<T> &lhs,
726  const segment_vector<T, Policy> &rhs);
727 template <typename T, typename Policy>
728 bool operator>(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs);
729 template <typename T, typename Policy>
730 bool operator>=(const std::vector<T> &lhs,
731  const segment_vector<T, Policy> &rhs);
732 
741 template <typename T, typename Policy>
743 {
744 }
745 
768 template <typename T, typename Policy>
770  const value_type &value)
771 {
772  internal_reserve(count);
773  construct(0, count, value);
774 }
775 
797 template <typename T, typename Policy>
799 {
800  internal_reserve(count);
801  construct(0, count);
802 }
803 
830 template <typename T, typename Policy>
831 template <typename InputIt,
832  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
833  InputIt>::type *>
834 segment_vector<T, Policy>::segment_vector(InputIt first, InputIt last)
835 {
836  internal_reserve(static_cast<size_type>(std::distance(first, last)));
837  construct_range(0, first, last);
838 }
839 
861 template <typename T, typename Policy>
863 {
864  internal_reserve(other.capacity());
865  construct_range(0, other.cbegin(), other.cend());
866 }
867 
888 template <typename T, typename Policy>
890 {
891  _data = std::move(other._data);
892  _segments_used = other._segments_used;
893  other._segments_used = 0;
894 }
895 
917 template <typename T, typename Policy>
918 segment_vector<T, Policy>::segment_vector(std::initializer_list<T> init)
919  : segment_vector(init.begin(), init.end())
920 {
921 }
922 
944 template <typename T, typename Policy>
945 segment_vector<T, Policy>::segment_vector(const std::vector<T> &other)
946  : segment_vector(other.cbegin(), other.cend())
947 {
948 }
949 
967 template <typename T, typename Policy>
970 {
971  assign(other);
972  return *this;
973 }
974 
990 template <typename T, typename Policy>
993 {
994  assign(std::move(other));
995  return *this;
996 }
997 
1015 template <typename T, typename Policy>
1017 segment_vector<T, Policy>::operator=(std::initializer_list<T> ilist)
1018 {
1019  assign(ilist.begin(), ilist.end());
1020  return *this;
1021 }
1022 
1040 template <typename T, typename Policy>
1042 segment_vector<T, Policy>::operator=(const std::vector<T> &other)
1043 {
1044  assign(other);
1045  return *this;
1046 }
1047 
1070 template <typename T, typename Policy>
1071 void
1072 segment_vector<T, Policy>::assign(size_type count, const_reference value)
1073 {
1074  if (count > max_size())
1075  throw std::length_error("Assignable range exceeds max size.");
1076 
1077  pool_base pb = get_pool();
1078  flat_transaction::run(pb, [&] {
1079  if (count > capacity())
1080  internal_reserve(count);
1081  else if (count < size())
1082  shrink(count);
1083 
1088  if (count != 0) {
1089  size_type end = policy::get_segment(count - 1);
1090  for (size_type i = 0; i < end; ++i)
1091  _data[i].assign(policy::segment_size(i), value);
1092  _data[end].assign(count - policy::segment_top(end),
1093  value);
1094 
1095  _segments_used = end + 1;
1096  }
1097  });
1098  assert(segment_capacity_validation());
1099 }
1100 
1123 template <typename T, typename Policy>
1124 template <typename InputIt,
1125  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1126  InputIt>::type *>
1127 void
1128 segment_vector<T, Policy>::assign(InputIt first, InputIt last)
1129 {
1130  size_type count = static_cast<size_type>(std::distance(first, last));
1131  if (count > max_size())
1132  throw std::length_error("Assignable range exceeds max size.");
1133 
1134  pool_base pb = get_pool();
1135  flat_transaction::run(pb, [&] {
1136  if (count > capacity())
1137  internal_reserve(count);
1138  else if (count < size())
1139  shrink(count);
1140 
1145  if (count != 0) {
1146  difference_type num;
1147  size_type end = policy::get_segment(count - 1);
1148  for (size_type i = 0; i < end; ++i) {
1149  size_type size = policy::segment_size(i);
1150  num = static_cast<difference_type>(size);
1151  _data[i].assign(first, std::next(first, num));
1152  std::advance(first, num);
1153  }
1154  num = static_cast<difference_type>(
1155  std::distance(first, last));
1156  _data[end].assign(first, std::next(first, num));
1157 
1158  _segments_used = end + 1;
1159  }
1160  });
1161  assert(segment_capacity_validation());
1162 }
1163 
1184 template <typename T, typename Policy>
1185 void
1186 segment_vector<T, Policy>::assign(std::initializer_list<T> ilist)
1187 {
1188  assign(ilist.begin(), ilist.end());
1189 }
1190 
1207 template <typename T, typename Policy>
1208 void
1210 {
1211  if (this != &other)
1212  assign(other.cbegin(), other.cend());
1213 }
1214 
1230 template <typename T, typename Policy>
1231 void
1233 {
1234  if (this == &other)
1235  return;
1236 
1237  pool_base pb = get_pool();
1238  flat_transaction::run(pb, [&] {
1239  _data = std::move(other._data);
1240  _segments_used = other._segments_used;
1241  other._segments_used = 0;
1242  });
1243 }
1244 
1261 template <typename T, typename Policy>
1262 void
1263 segment_vector<T, Policy>::assign(const std::vector<T> &other)
1264 {
1265  assign(other.cbegin(), other.cend());
1266 }
1267 
1275 template <typename T, typename Policy>
1277 {
1278  try {
1279  free_data();
1280  } catch (...) {
1281  std::terminate();
1282  }
1283 }
1284 
1298 template <typename T, typename Policy>
1299 typename segment_vector<T, Policy>::reference
1301 {
1302  if (n >= size())
1303  throw std::out_of_range("segment_vector::at");
1304 
1305  detail::conditional_add_to_tx(&get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1306 
1307  return get(n);
1308 }
1309 
1320 template <typename T, typename Policy>
1321 typename segment_vector<T, Policy>::const_reference
1323 {
1324  if (n >= size())
1325  throw std::out_of_range("segment_vector::at");
1326  return get(n);
1327 }
1328 
1341 template <typename T, typename Policy>
1342 typename segment_vector<T, Policy>::const_reference
1344 {
1345  if (n >= size())
1346  throw std::out_of_range("segment_vector::const_at");
1347  return get(n);
1348 }
1349 
1361 template <typename T, typename Policy>
1362 typename segment_vector<T, Policy>::reference
1364 {
1365  reference element = get(n);
1366 
1367  detail::conditional_add_to_tx(&element, 1,
1368  POBJ_XADD_ASSUME_INITIALIZED);
1369 
1370  return element;
1371 }
1372 
1380 template <typename T, typename Policy>
1381 typename segment_vector<T, Policy>::const_reference
1383 {
1384  return get(n);
1385 }
1386 
1395 template <typename T, typename Policy>
1396 typename segment_vector<T, Policy>::reference
1398 {
1399  detail::conditional_add_to_tx(&_data[0][0], 1,
1400  POBJ_XADD_ASSUME_INITIALIZED);
1401 
1402  return _data[0][0];
1403 }
1404 
1410 template <typename T, typename Policy>
1411 typename segment_vector<T, Policy>::const_reference
1413 {
1414  return _data[0][0];
1415 }
1416 
1424 template <typename T, typename Policy>
1425 typename segment_vector<T, Policy>::const_reference
1427 {
1428  return _data[0][0];
1429 }
1430 
1439 template <typename T, typename Policy>
1440 typename segment_vector<T, Policy>::reference
1442 {
1443  reference element = get(size() - 1);
1444 
1445  detail::conditional_add_to_tx(&element, 1,
1446  POBJ_XADD_ASSUME_INITIALIZED);
1447 
1448  return element;
1449 }
1450 
1456 template <typename T, typename Policy>
1457 typename segment_vector<T, Policy>::const_reference
1459 {
1460  return get(size() - 1);
1461 }
1462 
1470 template <typename T, typename Policy>
1471 typename segment_vector<T, Policy>::const_reference
1473 {
1474  return get(size() - 1);
1475 }
1476 
1482 template <typename T, typename Policy>
1485 {
1486  return iterator(this, 0);
1487 }
1488 
1495 template <typename T, typename Policy>
1498 {
1499  return const_iterator(this, 0);
1500 }
1501 
1510 template <typename T, typename Policy>
1513 {
1514  return const_iterator(this, 0);
1515 }
1516 
1523 template <typename T, typename Policy>
1526 {
1527  return iterator(this, size());
1528 }
1529 
1536 template <typename T, typename Policy>
1539 {
1540  return const_iterator(this, size());
1541 }
1542 
1551 template <typename T, typename Policy>
1554 {
1555  return const_iterator(this, size());
1556 }
1557 
1564 template <typename T, typename Policy>
1565 typename segment_vector<T, Policy>::reverse_iterator
1567 {
1568  return reverse_iterator(end());
1569 }
1570 
1577 template <typename T, typename Policy>
1578 typename segment_vector<T, Policy>::const_reverse_iterator
1580 {
1581  return const_reverse_iterator(end());
1582 }
1583 
1592 template <typename T, typename Policy>
1593 typename segment_vector<T, Policy>::const_reverse_iterator
1595 {
1596  return rbegin();
1597 }
1598 
1605 template <typename T, typename Policy>
1606 typename segment_vector<T, Policy>::reverse_iterator
1608 {
1609  return reverse_iterator(begin());
1610 }
1611 
1618 template <typename T, typename Policy>
1619 typename segment_vector<T, Policy>::const_reverse_iterator
1621 {
1622  return const_reverse_iterator(begin());
1623 }
1624 
1633 template <typename T, typename Policy>
1634 typename segment_vector<T, Policy>::const_reverse_iterator
1636 {
1637  return rend();
1638 }
1639 
1653 template <typename T, typename Policy>
1655 segment_vector<T, Policy>::range(size_type start, size_type n)
1656 {
1657  if (start + n > size())
1658  throw std::out_of_range("segment_vector::range");
1659 
1660  snapshot_data(start, start + n);
1661 
1662  return {iterator(this, start), iterator(this, start + n)};
1663 }
1664 
1676 template <typename T, typename Policy>
1678 segment_vector<T, Policy>::range(size_type start, size_type n) const
1679 {
1680  if (start + n > size())
1681  throw std::out_of_range("segment_vector::range");
1682 
1683  return {const_iterator(this, start), const_iterator(this, start + n)};
1684 }
1685 
1697 template <typename T, typename Policy>
1699 segment_vector<T, Policy>::crange(size_type start, size_type n) const
1700 {
1701  if (start + n > size())
1702  throw std::out_of_range("segment_vector::range");
1703 
1704  return {const_iterator(this, start), const_iterator(this, start + n)};
1705 }
1706 
1712 template <typename T, typename Policy>
1713 constexpr bool
1715 {
1716  return size() == 0;
1717 }
1718 
1722 template <typename T, typename Policy>
1723 typename segment_vector<T, Policy>::size_type
1725 {
1726  size_type result = 0;
1727 
1728  try {
1729  for (size_type i = 0; i < _segments_used; ++i)
1730  result += _data.const_at(i).size();
1731  } catch (std::out_of_range &) {
1732  /* Can only happen in case of a bug with segments_used calc */
1733  assert(false);
1734  }
1735 
1736  return result;
1737 }
1738 
1743 template <typename T, typename Policy>
1744 constexpr typename segment_vector<T, Policy>::size_type
1746 {
1747  return policy::max_size(_data);
1748 }
1749 
1766 template <typename T, typename Policy>
1767 void
1768 segment_vector<T, Policy>::reserve(size_type capacity_new)
1769 {
1770  if (capacity_new <= capacity())
1771  return;
1772 
1773  pool_base pb = get_pool();
1774  flat_transaction::run(pb, [&] { internal_reserve(capacity_new); });
1775 }
1776 
1781 template <typename T, typename Policy>
1782 typename segment_vector<T, Policy>::size_type
1784 {
1785  if (_segments_used == 0)
1786  return 0;
1787  return policy::capacity(_segments_used - 1);
1788 }
1789 
1801 template <typename T, typename Policy>
1802 void
1804 {
1805  if (empty())
1806  return;
1807  size_type new_last = policy::get_segment(size() - 1);
1808  if (_segments_used - 1 == new_last)
1809  return;
1810 
1811  pool_base pb = get_pool();
1812  flat_transaction::run(pb, [&] {
1813  for (size_type i = new_last + 1; i < _segments_used; ++i)
1814  _data[i].free_data();
1815  _segments_used = new_last + 1;
1816  storage::resize(_data, _segments_used);
1817  });
1818 }
1819 
1831 template <typename T, typename Policy>
1832 void
1834 {
1835  pool_base pb = get_pool();
1836  flat_transaction::run(pb, [&] { shrink(0); });
1837  assert(segment_capacity_validation());
1838 }
1839 
1852 template <typename T, typename Policy>
1853 void
1855 {
1856  pool_base pb = get_pool();
1857  flat_transaction::run(pb, [&] {
1858  for (size_type i = 0; i < _segments_used; ++i)
1859  _data[i].free_data();
1860  _segments_used = 0;
1861  });
1862 }
1863 
1887 template <typename T, typename Policy>
1890 {
1891  return insert(pos, 1, value);
1892 }
1893 
1917 template <typename T, typename Policy>
1920 {
1921  size_type idx = static_cast<size_type>(pos - cbegin());
1922 
1923  pool_base pb = get_pool();
1924  flat_transaction::run(pb, [&] {
1925  insert_gap(idx, 1);
1926  get(idx) = std::move(value);
1927  });
1928 
1929  return iterator(this, idx);
1930 }
1931 
1958 template <typename T, typename Policy>
1961  const T &value)
1962 {
1963  size_type idx = static_cast<size_type>(pos - cbegin());
1964 
1965  pool_base pb = get_pool();
1966  flat_transaction::run(pb, [&] {
1967  insert_gap(idx, count);
1968  for (size_type i = idx; i < idx + count; ++i)
1969  get(i) = std::move(value);
1970  });
1971 
1972  return iterator(this, idx);
1973 }
1974 
2008 template <typename T, typename Policy>
2009 template <typename InputIt,
2010  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2011  InputIt>::type *>
2014  InputIt last)
2015 {
2016  size_type idx = static_cast<size_type>(pos - cbegin());
2017  size_type gap_size = static_cast<size_type>(std::distance(first, last));
2018 
2019  pool_base pb = get_pool();
2020  flat_transaction::run(pb, [&] {
2021  insert_gap(idx, gap_size);
2022  for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2023  get(i) = *first;
2024  });
2025 
2026  return iterator(this, idx);
2027 }
2028 
2055 template <typename T, typename Policy>
2058  std::initializer_list<T> ilist)
2059 {
2060  return insert(pos, ilist.begin(), ilist.end());
2061 }
2062 
2091 template <typename T, typename Policy>
2092 template <class... Args>
2095 {
2096  size_type idx = static_cast<size_type>(pos - cbegin());
2097 
2098  pool_base pb = get_pool();
2099  flat_transaction::run(pb, [&] {
2100  detail::temp_value<value_type,
2101  noexcept(T(std::forward<Args>(args)...))>
2102  tmp(std::forward<Args>(args)...);
2103  insert_gap(idx, 1);
2104  get(idx) = std::move(tmp.get());
2105  });
2106 
2107  return iterator(this, idx);
2108 }
2109 
2134 template <typename T, typename Policy>
2135 template <class... Args>
2136 typename segment_vector<T, Policy>::reference
2138 {
2139  assert(size() < max_size());
2140 
2141  pool_base pb = get_pool();
2142  flat_transaction::run(pb, [&] {
2143  if (size() == capacity())
2144  internal_reserve(capacity() + 1);
2145 
2146  size_type segment = policy::get_segment(size());
2147  _data[segment].emplace_back(std::forward<Args>(args)...);
2148  });
2149 
2150  return back();
2151 }
2152 
2174 template <typename T, typename Policy>
2177 {
2178  return erase(pos, pos + 1);
2179 }
2180 
2205 template <typename T, typename Policy>
2208 {
2209  size_type count = static_cast<size_type>(std::distance(first, last));
2210  size_type idx = static_cast<size_type>(first - cbegin());
2211 
2212  if (count == 0)
2213  return iterator(this, idx);
2214 
2215  pool_base pb = get_pool();
2216  flat_transaction::run(pb, [&] {
2217  size_type _size = size();
2218 
2219  if (!std::is_trivially_destructible<T>::value ||
2220  idx + count < _size)
2221  snapshot_data(idx, _size);
2222 
2223  /* Moving after-range elements to the place of deleted
2224  */
2225  iterator dest = iterator(this, idx);
2226  iterator begin = iterator(this, idx + count);
2227  iterator end = iterator(this, _size);
2228  std::move(begin, end, dest);
2229 
2230  /* Clearing the range where the elements were moved from
2231  */
2232  size_type middle = policy::get_segment(_size - count);
2233  size_type last = policy::get_segment(_size - 1);
2234  size_type middle_size = policy::index_in_segment(_size - count);
2235  for (size_type s = last; s > middle; --s)
2236  _data[s].clear();
2237  _data[middle].resize(middle_size);
2238 
2239  _segments_used = middle + 1;
2240  });
2241 
2242  assert(segment_capacity_validation());
2243 
2244  return iterator(this, idx);
2245 }
2246 
2265 template <typename T, typename Policy>
2266 void
2268 {
2269  emplace_back(value);
2270 }
2271 
2290 template <typename T, typename Policy>
2291 void
2293 {
2294  emplace_back(std::move(value));
2295 }
2296 
2310 template <typename T, typename Policy>
2311 void
2313 {
2314  if (empty())
2315  return;
2316 
2317  pool_base pb = get_pool();
2318  flat_transaction::run(pb, [&] { shrink(size() - 1); });
2319  assert(segment_capacity_validation());
2320 }
2321 
2345 template <typename T, typename Policy>
2346 void
2348 {
2349  pool_base pb = get_pool();
2350  flat_transaction::run(pb, [&] {
2351  size_type _size = size();
2352  if (count < _size)
2353  shrink(count);
2354  else {
2355  if (capacity() < count)
2356  internal_reserve(count);
2357  construct(_size, count - _size);
2358  }
2359  });
2360  assert(segment_capacity_validation());
2361 }
2362 
2387 template <typename T, typename Policy>
2388 void
2389 segment_vector<T, Policy>::resize(size_type count, const value_type &value)
2390 {
2391  pool_base pb = get_pool();
2392  flat_transaction::run(pb, [&] {
2393  size_type _size = size();
2394  if (count < _size)
2395  shrink(count);
2396  else {
2397  if (capacity() < count)
2398  internal_reserve(count);
2399  construct(_size, count - _size, value);
2400  }
2401  });
2402  assert(segment_capacity_validation());
2403 }
2404 
2408 template <typename T, typename Policy>
2409 void
2411 {
2412  pool_base pb = get_pool();
2413  flat_transaction::run(pb, [&] {
2414  _data.swap(other._data);
2415  std::swap(_segments_used, other._segments_used);
2416  });
2417 }
2418 
2434 template <typename T, typename Policy>
2435 void
2436 segment_vector<T, Policy>::internal_reserve(size_type new_capacity)
2437 {
2438  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2439 
2440  if (new_capacity > max_size())
2441  throw std::length_error("New capacity exceeds max size.");
2442 
2443  if (new_capacity == 0)
2444  return;
2445 
2446  size_type old_idx = policy::get_segment(capacity());
2447  size_type new_idx = policy::get_segment(new_capacity - 1);
2448  storage::resize(_data, new_idx + 1);
2449  for (size_type i = old_idx; i <= new_idx; ++i) {
2450  size_type segment_capacity = policy::segment_size(i);
2451  _data[i].reserve(segment_capacity);
2452  }
2453  _segments_used = new_idx + 1;
2454 
2455  assert(segment_capacity_validation());
2456 }
2457 
2484 template <typename T, typename Policy>
2485 template <typename... Args>
2486 void
2487 segment_vector<T, Policy>::construct(size_type idx, size_type count,
2488  Args &&... args)
2489 {
2490  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2491  assert(capacity() >= size() + count);
2492 
2493  for (size_type i = idx; i < idx + count; ++i) {
2494  size_type segment = policy::get_segment(i);
2495  _data[segment].emplace_back(std::forward<Args>(args)...);
2496  }
2497 
2498  assert(segment_capacity_validation());
2499 }
2500 
2531 template <typename T, typename Policy>
2532 template <typename InputIt,
2533  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2534  InputIt>::type *>
2535 void
2536 segment_vector<T, Policy>::construct_range(size_type idx, InputIt first,
2537  InputIt last)
2538 {
2539  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2540  size_type count = static_cast<size_type>(std::distance(first, last));
2541  assert(capacity() >= size() + count);
2542 
2543  for (size_type i = idx; i < idx + count; ++i, ++first) {
2544  size_type segment = policy::get_segment(i);
2545  _data[segment].emplace_back(*first);
2546  }
2547 
2548  assert(segment_capacity_validation());
2549 }
2550 
2572 template <typename T, typename Policy>
2573 void
2574 segment_vector<T, Policy>::insert_gap(size_type idx, size_type count)
2575 {
2576  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2577  if (count == 0)
2578  return;
2579 
2580  size_type _size = size();
2581 
2582  if (capacity() < _size + count)
2583  internal_reserve(_size + count);
2584 
2585  iterator dest = iterator(this, _size + count);
2586  iterator begin = iterator(this, idx);
2587  iterator end = iterator(this, _size);
2588 
2589  snapshot_data(idx, _size);
2590 
2591  resize(_size + count);
2592  std::move_backward(begin, end, dest);
2593 
2594  assert(segment_capacity_validation());
2595 }
2596 
2616 template <typename T, typename Policy>
2617 void
2618 segment_vector<T, Policy>::shrink(size_type size_new)
2619 {
2620  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2621  assert(size_new <= size());
2622 
2623  if (empty())
2624  return;
2625 
2626  if (!std::is_trivially_destructible<T>::value)
2627  snapshot_data(size_new, size());
2628 
2629  size_type begin = policy::get_segment(size() - 1);
2630  size_type end = policy::get_segment(size_new);
2631  for (; begin > end; --begin) {
2632  _data[begin].clear();
2633  }
2634  size_type residue = policy::index_in_segment(size_new);
2635  _data[end].erase(_data[end].cbegin() + residue, _data[end].cend());
2636 
2637  assert(segment_capacity_validation());
2638 }
2639 
2647 template <typename T, typename Policy>
2648 pool_base
2649 segment_vector<T, Policy>::get_pool() const
2650 {
2651  return pmem::obj::pool_by_vptr(this);
2652 }
2653 
2663 template <typename T, typename Policy>
2664 void
2665 segment_vector<T, Policy>::snapshot_data(size_type first, size_type last)
2666 {
2667  if (first == last)
2668  return;
2669 
2670  size_type segment = policy::get_segment(first);
2671  size_type end = policy::get_segment(last - 1);
2672  size_type count = policy::segment_top(segment + 1) - first;
2673 
2674  while (segment != end) {
2675  detail::conditional_add_to_tx(&cget(first), count,
2676  POBJ_XADD_ASSUME_INITIALIZED);
2677  first = policy::segment_top(++segment);
2678  count = policy::segment_size(segment);
2679  }
2680  detail::conditional_add_to_tx(&cget(first), last - first,
2681  POBJ_XADD_ASSUME_INITIALIZED);
2682 }
2683 
2689 template <typename T, typename Policy>
2690 typename segment_vector<T, Policy>::reference
2691 segment_vector<T, Policy>::get(size_type n)
2692 {
2693  size_type s_idx = policy::get_segment(n);
2694  size_type local_idx = policy::index_in_segment(n);
2695 
2696  return _data[s_idx][local_idx];
2697 }
2698 
2704 template <typename T, typename Policy>
2705 typename segment_vector<T, Policy>::const_reference
2706 segment_vector<T, Policy>::get(size_type n) const
2707 {
2708  size_type s_idx = policy::get_segment(n);
2709  size_type local_idx = policy::index_in_segment(n);
2710 
2711  return _data[s_idx][local_idx];
2712 }
2713 
2719 template <typename T, typename Policy>
2720 typename segment_vector<T, Policy>::const_reference
2721 segment_vector<T, Policy>::cget(size_type n) const
2722 {
2723  size_type s_idx = policy::get_segment(n);
2724  size_type local_idx = policy::index_in_segment(n);
2725 
2726  return _data[s_idx][local_idx];
2727 }
2728 
2736 template <typename T, typename Policy>
2737 bool
2738 segment_vector<T, Policy>::segment_capacity_validation() const
2739 {
2740  for (size_type i = 0; i < _segments_used; ++i)
2741  if (_data.const_at(i).capacity() != policy::segment_size(i))
2742  return false;
2743  return true;
2744 }
2745 
2753 template <typename T, typename Policy>
2754 void
2756 {
2757  lhs.swap(rhs);
2758 }
2759 
2775 template <typename T, typename Policy>
2776 bool
2778  const segment_vector<T, Policy> &rhs)
2779 {
2780  return lhs.size() == rhs.size() &&
2781  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2782 }
2783 
2800 template <typename T, typename Policy>
2801 bool
2803  const segment_vector<T, Policy> &rhs)
2804 {
2805  return !(lhs == rhs);
2806 }
2807 
2821 template <typename T, typename Policy>
2822 bool
2823 operator<(const segment_vector<T, Policy> &lhs,
2824  const segment_vector<T, Policy> &rhs)
2825 {
2826  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2827  rhs.end());
2828 }
2829 
2843 template <typename T, typename Policy>
2844 bool
2845 operator<=(const segment_vector<T, Policy> &lhs,
2846  const segment_vector<T, Policy> &rhs)
2847 {
2848  return !(rhs < lhs);
2849 }
2850 
2864 template <typename T, typename Policy>
2865 bool
2867  const segment_vector<T, Policy> &rhs)
2868 {
2869  return rhs < lhs;
2870 }
2871 
2885 template <typename T, typename Policy>
2886 bool
2888  const segment_vector<T, Policy> &rhs)
2889 {
2890  return !(lhs < rhs);
2891 }
2892 
2907 template <typename T, typename Policy>
2908 bool
2909 operator==(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
2910 {
2911  return lhs.size() == rhs.size() &&
2912  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2913 }
2914 
2929 template <typename T, typename Policy>
2930 bool
2931 operator!=(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
2932 {
2933  return !(lhs == rhs);
2934 }
2935 
2948 template <typename T, typename Policy>
2949 bool
2950 operator<(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
2951 {
2952  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2953  rhs.end());
2954 }
2955 
2968 template <typename T, typename Policy>
2969 bool
2970 operator<=(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
2971 {
2972  return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2973  lhs.begin(), lhs.end()));
2974 }
2975 
2989 template <typename T, typename Policy>
2990 bool
2991 operator>(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
2992 {
2993  return !(lhs <= rhs);
2994 }
2995 
3008 template <typename T, typename Policy>
3009 bool
3010 operator>=(const segment_vector<T, Policy> &lhs, const std::vector<T> &rhs)
3011 {
3012  return !(lhs < rhs);
3013 }
3014 
3029 template <typename T, typename Policy>
3030 bool
3031 operator==(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3032 {
3033  return rhs == lhs;
3034 }
3035 
3050 template <typename T, typename Policy>
3051 bool
3052 operator!=(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3053 {
3054  return !(lhs == rhs);
3055 }
3056 
3069 template <typename T, typename Policy>
3070 bool
3071 operator<(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3072 {
3073  return rhs > lhs;
3074 }
3075 
3088 template <typename T, typename Policy>
3089 bool
3090 operator<=(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3091 {
3092  return !(rhs < lhs);
3093 }
3094 
3108 template <typename T, typename Policy>
3109 bool
3110 operator>(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3111 {
3112  return rhs < lhs;
3113 }
3114 
3127 template <typename T, typename Policy>
3128 bool
3129 operator>=(const std::vector<T> &lhs, const segment_vector<T, Policy> &rhs)
3130 {
3131  return !(lhs < rhs);
3132 }
3133 
3134 } /* namespace obj */
3135 } /* namespace pmem */
3136 
3137 #endif /* LIBPMEMOBJ_SEGMENT_VECTOR_HPP */
Array container with std::array compatible interface.
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
The non-template pool base class.
Definition: pool.hpp:51
Iterator for segment_vector.
Definition: segment_vector.hpp:46
segment_iterator & operator-=(difference_type idx)
Random access decrementing with assignment.
Definition: segment_vector.hpp:266
segment_iterator operator-(difference_type idx) const
Random access decrementing.
Definition: segment_vector.hpp:254
bool operator==(const segment_iterator< Container, C > &rhs) const
Compare methods Template parameter is needed to enable this methods work with non-constant and consta...
Definition: segment_vector.hpp:310
segment_iterator() noexcept
Default constructor.
Definition: segment_vector.hpp:132
bool operator<=(const segment_iterator< Container, C > &rhs) const
Less or equal operator.
Definition: segment_vector.hpp:392
bool operator>(const segment_iterator< Container, C > &rhs) const
Greater operator.
Definition: segment_vector.hpp:369
pointer operator->() const
Member access.
Definition: segment_vector.hpp:439
bool operator<(const segment_iterator< Container, C > &rhs) const
Less operator.
Definition: segment_vector.hpp:346
segment_iterator operator+(difference_type idx) const
Random access incrementing.
Definition: segment_vector.hpp:202
segment_iterator & operator--()
Prefix decrement.
Definition: segment_vector.hpp:227
reference operator*() const
Indirection (dereference).
Definition: segment_vector.hpp:429
segment_iterator & operator++()
Prefix increment.
Definition: segment_vector.hpp:175
bool operator!=(const segment_iterator< Container, C > &rhs) const
Not equal operator.
Definition: segment_vector.hpp:327
segment_iterator & operator+=(difference_type idx)
Random access incrementing with assignment.
Definition: segment_vector.hpp:214
bool operator>=(const segment_iterator< Container, C > &rhs) const
Greater or equal operator.
Definition: segment_vector.hpp:415
Persistent version of segment vector with std::vector compatible interface.
Definition: segment_vector.hpp:506
reference front()
Access the first element and add this element to a transaction.
Definition: segment_vector.hpp:1397
void reserve(size_type capacity_new)
Increases the capacity of the segment_vector to capacity_new transactionally.
Definition: segment_vector.hpp:1768
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: segment_vector.hpp:1714
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1594
size_type capacity() const noexcept
Definition: segment_vector.hpp:1783
bool operator>(const segment_vector< T, Policy > &lhs, const std::vector< T > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2991
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: segment_vector.hpp:1566
constexpr size_type max_size() const noexcept
Definition: segment_vector.hpp:1745
reference emplace_back(Args &&... args)
Appends a new element to the end of the container transactionally.
Definition: segment_vector.hpp:2137
reference at(size_type n)
Access element at specific index with bounds checking and add it to a transaction.
Definition: segment_vector.hpp:1300
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: segment_vector.hpp:1363
const_reference cfront() const
Access the first element.
Definition: segment_vector.hpp:1426
void swap(segment_vector &other)
Exchanges the contents of the container with other transactionally.
Definition: segment_vector.hpp:2410
void clear()
Clears the content of a segment_vector transactionally.
Definition: segment_vector.hpp:1833
bool operator>=(const segment_vector< T, Policy > &lhs, const std::vector< T > &rhs)
Comparison operator.
Definition: segment_vector.hpp:3010
~segment_vector()
Destructor.
Definition: segment_vector.hpp:1276
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: segment_vector.hpp:1343
const_reference cback() const
Access the last element.
Definition: segment_vector.hpp:1472
iterator begin()
Returns an iterator to the beginning.
Definition: segment_vector.hpp:1484
void resize(size_type count)
Resizes the container to count elements transactionally.
Definition: segment_vector.hpp:2347
bool operator==(const segment_vector< T, Policy > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2777
reference back()
Access the last element and add this element to a transaction.
Definition: segment_vector.hpp:1441
bool operator!=(const segment_vector< T, Policy > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2802
bool operator>=(const segment_vector< T, Policy > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2887
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1635
bool operator>=(const std::vector< T > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:3129
void push_back(const T &value)
Appends the given element value to the end of the container transactionally.
Definition: segment_vector.hpp:2267
slice< iterator > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: segment_vector.hpp:1655
size_type size() const noexcept
Definition: segment_vector.hpp:1724
bool operator==(const std::vector< T > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:3031
bool operator!=(const segment_vector< T, Policy > &lhs, const std::vector< T > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2931
void free_data()
Clears the content of a segment_vector and frees all allocated persistent memory for data transaction...
Definition: segment_vector.hpp:1854
iterator erase(const_iterator pos)
Removes the element at pos.
Definition: segment_vector.hpp:2176
bool operator==(const segment_vector< T, Policy > &lhs, const std::vector< T > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2909
iterator emplace(const_iterator pos, Args &&... args)
Inserts a new element into the container directly before pos.
Definition: segment_vector.hpp:2094
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: segment_vector.hpp:1607
segment_vector()
Default constructor.
Definition: segment_vector.hpp:742
segment_vector & operator=(const segment_vector &other)
Copy assignment operator.
Definition: segment_vector.hpp:969
iterator end()
Returns an iterator to past the end.
Definition: segment_vector.hpp:1525
void pop_back()
Removes the last element of the container transactionally.
Definition: segment_vector.hpp:2312
void shrink_to_fit()
Requests transactional removal of unused capacity.
Definition: segment_vector.hpp:1803
iterator insert(const_iterator pos, const T &value)
Inserts value before pos in the container transactionally.
Definition: segment_vector.hpp:1889
bool operator>(const std::vector< T > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:3110
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: segment_vector.hpp:1553
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: segment_vector.hpp:1699
bool operator>(const segment_vector< T, Policy > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:2866
bool operator!=(const std::vector< T > &lhs, const segment_vector< T, Policy > &rhs)
Comparison operator.
Definition: segment_vector.hpp:3052
void assign(size_type count, const_reference value)
Replaces the contents with count copies of value value transactionally.
Definition: segment_vector.hpp:1072
void swap(segment_vector< T, Policy > &lhs, segment_vector< T, Policy > &rhs)
Swaps the contents of lhs and rhs.
Definition: segment_vector.hpp:2755
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: segment_vector.hpp:1512
Provides interface to access sequence of objects.
Definition: slice.hpp:61
Persistent container with std::vector compatible interface.
Definition: vector.hpp:41
Commonly used functionality.
Functions for lifetime management.
persistent_ptr transactional allocation functions for objects.
void conditional_add_to_tx(const T *that, std::size_t count=1, uint64_t flags=0)
Conditionally add 'count' objects to a transaction.
Definition: common.hpp:176
segment_vector_internal::exponential_size_policy< pmem::obj::vector, SegmentType > exponential_size_vector_policy
Exponential size policy with pmemobj vector as a type of segment vector, so this is a dynamic vector ...
Definition: segment_vector.hpp:484
segment_vector_internal::fixed_size_policy< pmem::obj::vector, SegmentType, SegmentSize > fixed_size_vector_policy
Fixed size policy with pmemobj vector of a given size as a type of segment vector,...
Definition: segment_vector.hpp:471
segment_vector_internal::exponential_size_policy< segment_vector_internal::array_64, SegmentType > exponential_size_array_policy
Exponential size policy with pmemobj array of size 64 as a type of segment vector,...
Definition: segment_vector.hpp:457
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Convenience extensions for the resides on pmem property template.
A persistent version of segment vector implementation.
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:47
Template class for caching objects based on constructor's variadic template arguments and LIBPMEMOBJ_...
Definition: temp_value.hpp:35
Persistent container with std::array compatible interface.
Definition: array.hpp:57
template class for caching objects.
Commonly used SFINAE helpers.
C++ pmemobj transactions.
Libpmemobj C++ utils.
Vector container with std::vector compatible interface.