PMDK C++ bindings  1.8
This is the C++ bindings documentation for PMDK's libpmemobj.
segment_vector.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_SEGMENT_VECTOR_HPP
39 #define LIBPMEMOBJ_SEGMENT_VECTOR_HPP
40 
49 #include <libpmemobj++/pext.hpp>
51 
52 #include <vector>
53 
54 namespace pmem
55 {
56 namespace obj
57 {
58 namespace experimental
59 {
60 
61 namespace segment_vector_internal
62 {
70 template <typename Container, bool is_const>
72 public:
73  /* Traits */
74  using iterator_category = std::random_access_iterator_tag;
75  using difference_type = std::ptrdiff_t;
76  using table_type = Container;
77  using size_type = typename table_type::size_type;
78  using value_type = typename table_type::value_type;
79  /* Constant dependent traits */
80  using table_ptr =
81  typename std::conditional<is_const, const table_type *,
82  table_type *>::type;
83  using reference =
84  typename std::conditional<is_const,
85  typename table_type::const_reference,
86  typename table_type::reference>::type;
87  using pointer =
88  typename std::conditional<is_const,
89  typename table_type::const_pointer,
90  typename table_type::pointer>::type;
91 
92  /* To implement methods where operands differ in constancy */
93  friend class segment_iterator<Container, true>;
94  friend class segment_iterator<Container, false>;
95 
96 private:
97  /* Pointer to container for iteration */
98  table_ptr table;
99  /* Index of element in the container */
100  size_type index;
101 
102 public:
103  /* Сonstructors */
104  segment_iterator() noexcept;
105  explicit segment_iterator(table_ptr tab, size_type idx) noexcept;
106  segment_iterator(const segment_iterator &other);
107 
108  /* Copy ctor to enable conversion from non-const to const
109  * iterator */
110  template <typename U = void,
111  typename = typename std::enable_if<is_const, U>::type>
113 
114  /* In(de)crement methods */
115  segment_iterator &operator++();
116  segment_iterator operator++(int);
117  segment_iterator operator+(difference_type idx) const;
118  segment_iterator &operator+=(difference_type idx);
119  segment_iterator &operator--();
120  segment_iterator operator--(int);
121  segment_iterator operator-(difference_type idx) const;
122  segment_iterator &operator-=(difference_type idx);
123  template <bool C>
124  difference_type operator+(const segment_iterator<Container, C> &rhs);
125  template <bool C>
126  difference_type operator-(const segment_iterator<Container, C> &rhs);
127 
133  template <bool C>
135  template <bool C>
137  template <bool C>
138  bool operator<(const segment_iterator<Container, C> &rhs);
139  template <bool C>
140  bool operator>(const segment_iterator<Container, C> &rhs);
141  template <bool C>
142  bool operator<=(const segment_iterator<Container, C> &rhs);
143  template <bool C>
145 
146  /* Access methods */
147  reference operator*() const;
148  pointer operator->() const;
149 };
150 
154 template <typename Container, bool is_const>
156  : table(nullptr), index()
157 {
158 }
159 
164 template <typename Container, bool is_const>
166  size_type idx) noexcept
167  : table(tab), index(idx)
168 {
169 }
170 
175 template <typename Container, bool is_const>
177  const segment_iterator &other)
178 {
179  table = other.table;
180  index = other.index;
181 }
182 
184 template <typename Container, bool is_const>
185 template <typename U, typename>
188  : table(other.table), index(other.index)
189 {
190 }
191 
197 template <typename Container, bool is_const>
200 {
201  ++index;
202  return *this;
203 }
204 
210 template <typename Container, bool is_const>
213 {
214  auto iterator = *this;
215  ++*this;
216  return iterator;
217 }
218 
224 template <typename Container, bool is_const>
227 {
228  return segment_iterator(table, index + static_cast<size_type>(idx));
229 }
230 
236 template <typename Container, bool is_const>
239 {
240  index += static_cast<size_type>(idx);
241  return *this;
242 }
243 
249 template <typename Container, bool is_const>
252 {
253  --index;
254  return *this;
255 }
256 
262 template <typename Container, bool is_const>
265 {
266  auto iterator = *this;
267  --*this;
268  return iterator;
269 }
270 
276 template <typename Container, bool is_const>
279 {
280  return segment_iterator(table, index - static_cast<size_type>(idx));
281 }
282 
288 template <typename Container, bool is_const>
291 {
292  index -= static_cast<size_type>(idx);
293  return *this;
294 }
295 
301 template <typename Container, bool is_const>
302 template <bool C>
303 typename segment_iterator<Container, is_const>::difference_type
306 {
307  return static_cast<difference_type>(index + rhs.index);
308 }
309 
315 template <typename Container, bool is_const>
316 template <bool C>
317 typename segment_iterator<Container, is_const>::difference_type
320 {
321  return static_cast<difference_type>(index - rhs.index);
322 }
323 
331 template <typename Container, bool is_const>
332 template <bool C>
333 bool
336 {
337  return (table == rhs.table) && (index == rhs.index);
338 }
339 
348 template <typename Container, bool is_const>
349 template <bool C>
350 bool
353 {
354  return (table != rhs.table) || (index != rhs.index);
355 }
356 
367 template <typename Container, bool is_const>
368 template <bool C>
369 bool
372 {
373  if (table != rhs.table)
374  throw std::invalid_argument("segment_iterator::operator<");
375 
376  return index < rhs.index;
377 }
378 
390 template <typename Container, bool is_const>
391 template <bool C>
392 bool
395 {
396  if (table != rhs.table)
397  throw std::invalid_argument("segment_iterator::operator<");
398 
399  return index > rhs.index;
400 }
401 
413 template <typename Container, bool is_const>
414 template <bool C>
415 bool
418 {
419  if (table != rhs.table)
420  throw std::invalid_argument("segment_iterator::operator<");
421 
422  return index <= rhs.index;
423 }
424 
436 template <typename Container, bool is_const>
437 template <bool C>
438 bool
441 {
442  if (table != rhs.table)
443  throw std::invalid_argument("segment_iterator::operator<");
444 
445  return index >= rhs.index;
446 }
447 
451 template <typename Container, bool is_const>
452 typename segment_iterator<Container, is_const>::reference
454 {
455  return table->operator[](index);
456 }
457 
461 template <typename Container, bool is_const>
462 typename segment_iterator<Container, is_const>::pointer
464 {
465  return &operator*();
466 }
467 
468 template <typename Container>
469 using resize_method =
470  decltype(std::declval<Container>().resize(std::declval<size_t>()));
471 
472 template <typename Container>
473 using container_has_resize = detail::supports<Container, resize_method>;
474 
475 template <typename Container, bool = container_has_resize<Container>::value>
476 struct segment_vector_resize {
477  using segment_vector_type = Container;
478 
479  static void
480  resize(segment_vector_type &c, size_t n)
481  {
482  c.resize(n);
483  }
484 };
485 
486 template <typename Container>
487 struct segment_vector_resize<Container, false> {
488  using segment_vector_type = Container;
489 
490  static void
491  resize(segment_vector_type &c, size_t n)
492  {
493  }
494 };
495 
496 template <typename SegmentVectorType, size_t SegmentSize>
497 class fixed_size_policy {
498 public:
499  /* Traits */
500  using segment_vector_type = SegmentVectorType;
501  using segment_type = typename segment_vector_type::value_type;
502  using value_type = typename segment_type::value_type;
503  using size_type = std::size_t;
504 
505  using segment_vector_resize_type =
506  segment_vector_resize<segment_vector_type>;
507 
508  static constexpr size_type Size = SegmentSize;
509 
510  static void
511  resize(segment_vector_type &c, size_type n)
512  {
513  segment_vector_resize_type::resize(c, n);
514  }
515 
521  static size_type
522  get_segment(size_type index)
523  {
524  return index / Size;
525  }
531  static size_type
532  segment_top(size_type segment_index)
533  {
534  return segment_index * Size;
535  }
541  static size_type
542  segment_size(size_type segment_index)
543  {
544  return Size;
545  }
551  static size_type
552  index_in_segment(size_type index)
553  {
554  return index % Size;
555  }
556 
560  static size_type
561  max_size(const SegmentVectorType &seg_storage)
562  {
563  return seg_storage.max_size() * SegmentSize;
564  }
565 
569  static size_type
570  capacity(size_type segment_index)
571  {
572  return (segment_index + 1) * Size;
573  }
574 };
575 
576 template <typename SegmentVectorType>
577 class exponential_size_policy {
578 public:
579  /* Traits */
580  using segment_vector_type = SegmentVectorType;
581  using segment_type = typename segment_vector_type::value_type;
582  using value_type = typename segment_type::value_type;
583  using size_type = std::size_t;
584 
585  using segment_vector_resize_type =
586  segment_vector_resize<segment_vector_type>;
587 
588  static void
589  resize(segment_vector_type &c, size_type n)
590  {
591  segment_vector_resize_type::resize(c, n);
592  }
593 
599  static size_type
600  get_segment(size_type index)
601  {
602  return static_cast<size_type>(detail::Log2(index | 1));
603  }
609  static size_type
610  segment_top(size_type segment_index)
611  {
612  return (size_type(1) << segment_index) & ~size_type(1);
613  }
619  static size_type
620  segment_size(size_type segment_index)
621  {
622  return (segment_index == 0) ? 2 : segment_top(segment_index);
623  }
629  static size_type
630  index_in_segment(size_type index)
631  {
632  return index - segment_top(get_segment(index));
633  }
634 
638  static size_t
639  max_size(const SegmentVectorType &)
640  {
641  return segment_size(get_segment(PMEMOBJ_MAX_ALLOC_SIZE /
642  sizeof(value_type)) +
643  1);
644  }
645 
649  static size_type
650  capacity(size_type segment_index)
651  {
652  if (segment_index == 0)
653  return 2;
654  return segment_size(segment_index) * 2;
655  }
656 };
657 
658 } /* segment_vector_internal namespace */
659 
660 template <typename SegmentType>
661 using exponential_size_array_policy =
662  segment_vector_internal::exponential_size_policy<
664 
669 template <typename SegmentType, size_t SegmentSize>
670 using fixed_size_array_policy = segment_vector_internal::fixed_size_policy<
672 
673 template <typename SegmentType, size_t SegmentSize>
674 using fixed_size_vector_policy = segment_vector_internal::fixed_size_policy<
675  pmem::obj::vector<SegmentType>, SegmentSize>;
676 
677 template <typename SegmentType>
678 using exponential_size_vector_policy =
679  segment_vector_internal::exponential_size_policy<
680  pmem::obj::vector<SegmentType>>;
681 
708 template <typename T, typename Segment = pmem::obj::vector<T>,
709  typename Policy = exponential_size_array_policy<Segment>>
711 public:
712  /* Specific traits*/
713  using policy_type = Policy;
714  using segment_type = typename policy_type::segment_type;
715  using segment_vector_type = typename policy_type::segment_vector_type;
716  /* Simple access to methods */
717  using policy = policy_type;
718  using storage = policy_type;
719 
720  /* Traits */
721  using value_type = T;
722  using size_type = std::size_t;
723  using difference_type = std::ptrdiff_t;
724  using reference = value_type &;
725  using const_reference = const value_type &;
726  using pointer = value_type *;
727  using const_pointer = const value_type *;
728  using iterator =
730  false>;
731  using const_iterator =
733  using reverse_iterator = std::reverse_iterator<iterator>;
734  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
735 
736  /* Constructors */
737  segment_vector();
738  segment_vector(size_type count, const value_type &value);
739  explicit segment_vector(size_type count);
740  template <typename InputIt,
741  typename std::enable_if<
743  InputIt>::type * = nullptr>
744  segment_vector(InputIt first, InputIt last);
745  segment_vector(const segment_vector &other);
746  segment_vector(segment_vector &&other);
747  segment_vector(std::initializer_list<T> init);
748  segment_vector(const std::vector<T> &other);
749 
750  /* Assign operators */
751  segment_vector &operator=(const segment_vector &other);
752  segment_vector &operator=(segment_vector &&other);
753  segment_vector &operator=(std::initializer_list<T> ilist);
754  segment_vector &operator=(const std::vector<T> &other);
755 
756  /* Assign methods */
757  void assign(size_type count, const_reference value);
758  template <typename InputIt,
759  typename std::enable_if<
760  detail::is_input_iterator<InputIt>::value,
761  InputIt>::type * = nullptr>
762  void assign(InputIt first, InputIt last);
763  void assign(std::initializer_list<T> ilist);
764  void assign(const segment_vector &other);
765  void assign(segment_vector &&other);
766  void assign(const std::vector<T> &other);
767 
768  /* Destructor */
769  ~segment_vector();
770 
771  /* Element access */
772  reference at(size_type n);
773  const_reference at(size_type n) const;
774  const_reference const_at(size_type n) const;
775  reference operator[](size_type n);
776  const_reference operator[](size_type n) const;
777  reference front();
778  const_reference front() const;
779  const_reference cfront() const;
780  reference back();
781  const_reference back() const;
782  const_reference cback() const;
783 
784  /* Iterators */
785  iterator begin();
786  const_iterator begin() const noexcept;
787  const_iterator cbegin() const noexcept;
788  iterator end();
789  const_iterator end() const noexcept;
790  const_iterator cend() const noexcept;
791  reverse_iterator rbegin();
792  const_reverse_iterator rbegin() const noexcept;
793  const_reverse_iterator crbegin() const noexcept;
794  reverse_iterator rend();
795  const_reverse_iterator rend() const noexcept;
796  const_reverse_iterator crend() const noexcept;
797 
798  /* Range */
799  slice<iterator> range(size_type start, size_type n);
800  slice<const_iterator> range(size_type start, size_type n) const;
801  slice<const_iterator> crange(size_type start, size_type n) const;
802 
803  /* Capacity */
804  constexpr bool empty() const noexcept;
805  size_type size() const noexcept;
806  constexpr size_type max_size() const noexcept;
807  void reserve(size_type capacity_new);
808  size_type capacity() const noexcept;
809  void shrink_to_fit();
810 
811  /* Modifiers */
812  void clear();
813  void free_data();
814  iterator insert(const_iterator pos, const T &value);
815  iterator insert(const_iterator pos, T &&value);
816  iterator insert(const_iterator pos, size_type count, const T &value);
817  template <typename InputIt,
818  typename std::enable_if<
819  detail::is_input_iterator<InputIt>::value,
820  InputIt>::type * = nullptr>
821  iterator insert(const_iterator pos, InputIt first, InputIt last);
822  iterator insert(const_iterator pos, std::initializer_list<T> ilist);
823  template <class... Args>
824  iterator emplace(const_iterator pos, Args &&... args);
825  template <class... Args>
826  reference emplace_back(Args &&... args);
827  iterator erase(const_iterator pos);
828  iterator erase(const_iterator first, const_iterator last);
829  void push_back(const T &value);
830  void push_back(T &&value);
831  void pop_back();
832  void resize(size_type count);
833  void resize(size_type count, const value_type &value);
834  void swap(segment_vector &other);
835 
836 private:
837  /* Helper functions */
838  void internal_reserve(size_type new_capacity);
839  template <typename... Args>
840  void construct(size_type idx, size_type count, Args &&... args);
841  template <typename InputIt,
842  typename std::enable_if<
843  detail::is_input_iterator<InputIt>::value,
844  InputIt>::type * = nullptr>
845  void construct_range(size_type idx, InputIt first, InputIt last);
846  void insert_gap(size_type idx, size_type count);
847  void shrink(size_type size_new);
848  pool_base get_pool() const noexcept;
849  void snapshot_data(size_type idx_first, size_type idx_last);
850 
851  /* Data structure specific helper functions */
852  reference get(size_type n);
853  const_reference get(size_type n) const;
854  const_reference cget(size_type n) const;
855  bool segment_capacity_validation() const;
856 
857  /* Number of segments that currently enabled */
858  p<size_type> _segments_used = 0;
859  /* Segments storage */
860  segment_vector_type _data;
861 };
862 
863 /* Non-member swap */
864 template <typename T, typename Segment, typename Policy>
867 
868 /*
869  * Comparison operators between
870  * pmem::obj::experimental::segment_vector<T, Segment, Policy> and
871  * pmem::obj::experimental::segment_vector<T, Segment, Policy>
872  */
873 template <typename T, typename Segment, typename Policy>
876 template <typename T, typename Segment, typename Policy>
879 template <typename T, typename Segment, typename Policy>
880 bool operator<(const segment_vector<T, Segment, Policy> &lhs,
882 template <typename T, typename Segment, typename Policy>
883 bool operator<=(const segment_vector<T, Segment, Policy> &lhs,
885 template <typename T, typename Segment, typename Policy>
888 template <typename T, typename Segment, typename Policy>
891 
892 /*
893  * Comparison operators between
894  * pmem::obj::experimental::segment_vector<T, Segment, Policy> and
895  * std::vector<T>
896  */
897 template <typename T, typename Segment, typename Policy>
899  const std::vector<T> &rhs);
900 template <typename T, typename Segment, typename Policy>
902  const std::vector<T> &rhs);
903 template <typename T, typename Segment, typename Policy>
904 bool operator<(const segment_vector<T, Segment, Policy> &lhs,
905  const std::vector<T> &rhs);
906 template <typename T, typename Segment, typename Policy>
907 bool operator<=(const segment_vector<T, Segment, Policy> &lhs,
908  const std::vector<T> &rhs);
909 template <typename T, typename Segment, typename Policy>
911  const std::vector<T> &rhs);
912 template <typename T, typename Segment, typename Policy>
914  const std::vector<T> &rhs);
915 
916 /*
917  * Comparison operators between std::vector<T> and
918  * pmem::obj::experimental::segment_vector<T, Segment, Policy>
919  */
920 template <typename T, typename Segment, typename Policy>
921 bool operator==(const std::vector<T> &lhs,
923 template <typename T, typename Segment, typename Policy>
924 bool operator!=(const std::vector<T> &lhs,
926 template <typename T, typename Segment, typename Policy>
927 bool operator<(const std::vector<T> &lhs,
929 template <typename T, typename Segment, typename Policy>
930 bool operator<=(const std::vector<T> &lhs,
932 template <typename T, typename Segment, typename Policy>
933 bool operator>(const std::vector<T> &lhs,
935 template <typename T, typename Segment, typename Policy>
936 bool operator>=(const std::vector<T> &lhs,
938 
947 template <typename T, typename Segment, typename Policy>
949 {
950 }
951 
974 template <typename T, typename Segment, typename Policy>
976  const value_type &value)
977 {
978  internal_reserve(count);
979  construct(0, count, value);
980 }
981 
1003 template <typename T, typename Segment, typename Policy>
1005 {
1006  internal_reserve(count);
1007  construct(0, count);
1008 }
1009 
1036 template <typename T, typename Segment, typename Policy>
1037 template <typename InputIt,
1038  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1039  InputIt>::type *>
1041 {
1042  internal_reserve(static_cast<size_type>(std::distance(first, last)));
1043  construct_range(0, first, last);
1044 }
1045 
1067 template <typename T, typename Segment, typename Policy>
1069 {
1070  internal_reserve(other.capacity());
1071  construct_range(0, other.cbegin(), other.cend());
1072 }
1073 
1094 template <typename T, typename Segment, typename Policy>
1096 {
1097  _data = std::move(other._data);
1098  _segments_used = other._segments_used;
1099  other._segments_used = 0;
1100 }
1101 
1123 template <typename T, typename Segment, typename Policy>
1125  std::initializer_list<T> init)
1126  : segment_vector(init.begin(), init.end())
1127 {
1128 }
1129 
1151 template <typename T, typename Segment, typename Policy>
1153  : segment_vector(other.cbegin(), other.cend())
1154 {
1155 }
1156 
1174 template <typename T, typename Segment, typename Policy>
1177 {
1178  assign(other);
1179  return *this;
1180 }
1181 
1197 template <typename T, typename Segment, typename Policy>
1200 {
1201  assign(std::move(other));
1202  return *this;
1203 }
1204 
1222 template <typename T, typename Segment, typename Policy>
1224 segment_vector<T, Segment, Policy>::operator=(std::initializer_list<T> ilist)
1225 {
1226  assign(ilist.begin(), ilist.end());
1227  return *this;
1228 }
1229 
1247 template <typename T, typename Segment, typename Policy>
1250 {
1251  assign(other);
1252  return *this;
1253 }
1254 
1277 template <typename T, typename Segment, typename Policy>
1278 void
1280  const_reference value)
1281 {
1282  if (count > max_size())
1283  throw std::length_error("Assignable range exceeds max size.");
1284 
1285  pool_base pb = get_pool();
1286  transaction::run(pb, [&] {
1287  if (count > capacity())
1288  internal_reserve(count);
1289  else if (count < size())
1290  shrink(count);
1291 
1292  size_type end = policy::get_segment(count - 1);
1293  for (size_type i = 0; i < end; ++i)
1294  _data[i].assign(policy::segment_size(i), value);
1295  _data[end].assign(count - policy::segment_top(end), value);
1296 
1297  _segments_used = end + 1;
1298  });
1299  assert(segment_capacity_validation());
1300 }
1301 
1324 template <typename T, typename Segment, typename Policy>
1325 template <typename InputIt,
1326  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1327  InputIt>::type *>
1328 void
1330 {
1331  size_type count = static_cast<size_type>(std::distance(first, last));
1332  if (count > max_size())
1333  throw std::length_error("Assignable range exceeds max size.");
1334 
1335  pool_base pb = get_pool();
1336  transaction::run(pb, [&] {
1337  if (count > capacity())
1338  internal_reserve(count);
1339  else if (count < size())
1340  shrink(count);
1341 
1342  difference_type num;
1343  size_type end = policy::get_segment(count - 1);
1344  for (size_type i = 0; i < end; ++i) {
1345  size_type size = policy::segment_size(i);
1346  num = static_cast<difference_type>(size);
1347  _data[i].assign(first, std::next(first, num));
1348  std::advance(first, num);
1349  }
1350  num = static_cast<difference_type>(std::distance(first, last));
1351  _data[end].assign(first, std::next(first, num));
1352 
1353  _segments_used = end + 1;
1354  });
1355  assert(segment_capacity_validation());
1356 }
1357 
1378 template <typename T, typename Segment, typename Policy>
1379 void
1380 segment_vector<T, Segment, Policy>::assign(std::initializer_list<T> ilist)
1381 {
1382  assign(ilist.begin(), ilist.end());
1383 }
1384 
1401 template <typename T, typename Segment, typename Policy>
1402 void
1404 {
1405  if (this != &other)
1406  assign(other.cbegin(), other.cend());
1407 }
1408 
1424 template <typename T, typename Segment, typename Policy>
1425 void
1427 {
1428  if (this == &other)
1429  return;
1430 
1431  pool_base pb = get_pool();
1432  transaction::run(pb, [&] {
1433  _data = std::move(other._data);
1434  _segments_used = other._segments_used;
1435  other._segments_used = 0;
1436  });
1437 }
1438 
1455 template <typename T, typename Segment, typename Policy>
1456 void
1458 {
1459  assign(other.cbegin(), other.cend());
1460 }
1461 
1473 template <typename T, typename Segment, typename Policy>
1475 {
1476  free_data();
1477 }
1478 
1492 template <typename T, typename Segment, typename Policy>
1493 typename segment_vector<T, Segment, Policy>::reference
1495 {
1496  if (n >= size())
1497  throw std::out_of_range("segment_vector::at");
1498 
1499  detail::conditional_add_to_tx(&get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1500 
1501  return get(n);
1502 }
1503 
1514 template <typename T, typename Segment, typename Policy>
1515 typename segment_vector<T, Segment, Policy>::const_reference
1517 {
1518  if (n >= size())
1519  throw std::out_of_range("segment_vector::at");
1520  return get(n);
1521 }
1522 
1535 template <typename T, typename Segment, typename Policy>
1536 typename segment_vector<T, Segment, Policy>::const_reference
1538 {
1539  if (n >= size())
1540  throw std::out_of_range("segment_vector::const_at");
1541  return get(n);
1542 }
1543 
1555 template <typename T, typename Segment, typename Policy>
1556 typename segment_vector<T, Segment, Policy>::reference
1558 {
1559  reference element = get(n);
1560 
1561  detail::conditional_add_to_tx(&element, 1,
1562  POBJ_XADD_ASSUME_INITIALIZED);
1563 
1564  return element;
1565 }
1566 
1574 template <typename T, typename Segment, typename Policy>
1575 typename segment_vector<T, Segment, Policy>::const_reference
1577 {
1578  return get(n);
1579 }
1580 
1589 template <typename T, typename Segment, typename Policy>
1590 typename segment_vector<T, Segment, Policy>::reference
1592 {
1593  detail::conditional_add_to_tx(&_data[0][0], 1,
1594  POBJ_XADD_ASSUME_INITIALIZED);
1595 
1596  return _data[0][0];
1597 }
1598 
1604 template <typename T, typename Segment, typename Policy>
1605 typename segment_vector<T, Segment, Policy>::const_reference
1607 {
1608  return _data[0][0];
1609 }
1610 
1618 template <typename T, typename Segment, typename Policy>
1619 typename segment_vector<T, Segment, Policy>::const_reference
1621 {
1622  return _data[0][0];
1623 }
1624 
1633 template <typename T, typename Segment, typename Policy>
1634 typename segment_vector<T, Segment, Policy>::reference
1636 {
1637  reference element = get(size() - 1);
1638 
1639  detail::conditional_add_to_tx(&element, 1,
1640  POBJ_XADD_ASSUME_INITIALIZED);
1641 
1642  return element;
1643 }
1644 
1650 template <typename T, typename Segment, typename Policy>
1651 typename segment_vector<T, Segment, Policy>::const_reference
1653 {
1654  return get(size() - 1);
1655 }
1656 
1664 template <typename T, typename Segment, typename Policy>
1665 typename segment_vector<T, Segment, Policy>::const_reference
1667 {
1668  return get(size() - 1);
1669 }
1670 
1676 template <typename T, typename Segment, typename Policy>
1679 {
1680  return iterator(this, 0);
1681 }
1682 
1689 template <typename T, typename Segment, typename Policy>
1692 {
1693  return const_iterator(this, 0);
1694 }
1695 
1704 template <typename T, typename Segment, typename Policy>
1707 {
1708  return const_iterator(this, 0);
1709 }
1710 
1717 template <typename T, typename Segment, typename Policy>
1720 {
1721  return iterator(this, size());
1722 }
1723 
1730 template <typename T, typename Segment, typename Policy>
1733 {
1734  return const_iterator(this, size());
1735 }
1736 
1745 template <typename T, typename Segment, typename Policy>
1748 {
1749  return const_iterator(this, size());
1750 }
1751 
1758 template <typename T, typename Segment, typename Policy>
1759 typename segment_vector<T, Segment, Policy>::reverse_iterator
1761 {
1762  return reverse_iterator(end());
1763 }
1764 
1771 template <typename T, typename Segment, typename Policy>
1772 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1774 {
1775  return const_reverse_iterator(end());
1776 }
1777 
1786 template <typename T, typename Segment, typename Policy>
1787 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1789 {
1790  return rbegin();
1791 }
1792 
1799 template <typename T, typename Segment, typename Policy>
1800 typename segment_vector<T, Segment, Policy>::reverse_iterator
1802 {
1803  return reverse_iterator(begin());
1804 }
1805 
1812 template <typename T, typename Segment, typename Policy>
1813 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1815 {
1816  return const_reverse_iterator(begin());
1817 }
1818 
1827 template <typename T, typename Segment, typename Policy>
1828 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1830 {
1831  return rend();
1832 }
1833 
1847 template <typename T, typename Segment, typename Policy>
1849 segment_vector<T, Segment, Policy>::range(size_type start, size_type n)
1850 {
1851  if (start + n > size())
1852  throw std::out_of_range("segment_vector::range");
1853 
1854  snapshot_data(start, start + n);
1855 
1856  return {iterator(this, start), iterator(this, start + n)};
1857 }
1858 
1870 template <typename T, typename Segment, typename Policy>
1872 segment_vector<T, Segment, Policy>::range(size_type start, size_type n) const
1873 {
1874  if (start + n > size())
1875  throw std::out_of_range("segment_vector::range");
1876 
1877  return {const_iterator(this, start), const_iterator(this, start + n)};
1878 }
1879 
1891 template <typename T, typename Segment, typename Policy>
1893 segment_vector<T, Segment, Policy>::crange(size_type start, size_type n) const
1894 {
1895  if (start + n > size())
1896  throw std::out_of_range("segment_vector::range");
1897 
1898  return {const_iterator(this, start), const_iterator(this, start + n)};
1899 }
1900 
1906 template <typename T, typename Segment, typename Policy>
1907 constexpr bool
1909 {
1910  return size() == 0;
1911 }
1912 
1916 template <typename T, typename Segment, typename Policy>
1917 typename segment_vector<T, Segment, Policy>::size_type
1919 {
1920  size_type result = 0;
1921  for (size_type i = 0; i < _segments_used; ++i)
1922  result += _data.const_at(i).size();
1923  return result;
1924 }
1925 
1930 template <typename T, typename Segment, typename Policy>
1931 constexpr typename segment_vector<T, Segment, Policy>::size_type
1933 {
1934  return policy::max_size(_data);
1935 }
1936 
1953 template <typename T, typename Segment, typename Policy>
1954 void
1956 {
1957  if (capacity_new <= capacity())
1958  return;
1959 
1960  pool_base pb = get_pool();
1961  transaction::run(pb, [&] { internal_reserve(capacity_new); });
1962 }
1963 
1968 template <typename T, typename Segment, typename Policy>
1969 typename segment_vector<T, Segment, Policy>::size_type
1971 {
1972  if (_segments_used == 0)
1973  return 0;
1974  return policy::capacity(_segments_used - 1);
1975 }
1976 
1988 template <typename T, typename Segment, typename Policy>
1989 void
1991 {
1992  size_type new_last = policy::get_segment(size() - 1);
1993  if (_segments_used - 1 == new_last)
1994  return;
1995 
1996  pool_base pb = get_pool();
1997  transaction::run(pb, [&] {
1998  for (size_type i = new_last + 1; i < _segments_used; ++i)
1999  _data[i].free_data();
2000  _segments_used = new_last + 1;
2001  storage::resize(_data, _segments_used);
2002  });
2003 }
2004 
2016 template <typename T, typename Segment, typename Policy>
2017 void
2019 {
2020  pool_base pb = get_pool();
2021  transaction::run(pb, [&] { shrink(0); });
2022  assert(segment_capacity_validation());
2023 }
2024 
2037 template <typename T, typename Segment, typename Policy>
2038 void
2040 {
2041  pool_base pb = get_pool();
2042  transaction::run(pb, [&] {
2043  for (size_type i = 0; i < _segments_used; ++i)
2044  _data[i].free_data();
2045  _segments_used = 0;
2046  });
2047 }
2048 
2072 template <typename T, typename Segment, typename Policy>
2075 {
2076  return insert(pos, 1, value);
2077 }
2078 
2102 template <typename T, typename Segment, typename Policy>
2105 {
2106  size_type idx = static_cast<size_type>(pos - cbegin());
2107 
2108  pool_base pb = get_pool();
2109  transaction::run(pb, [&] {
2110  insert_gap(idx, 1);
2111  get(idx) = std::move(value);
2112  });
2113 
2114  return iterator(this, idx);
2115 }
2116 
2143 template <typename T, typename Segment, typename Policy>
2146  const T &value)
2147 {
2148  size_type idx = static_cast<size_type>(pos - cbegin());
2149 
2150  pool_base pb = get_pool();
2151  transaction::run(pb, [&] {
2152  insert_gap(idx, count);
2153  for (size_type i = idx; i < idx + count; ++i)
2154  get(i) = std::move(value);
2155  });
2156 
2157  return iterator(this, idx);
2158 }
2159 
2193 template <typename T, typename Segment, typename Policy>
2194 template <typename InputIt,
2195  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2196  InputIt>::type *>
2199  InputIt last)
2200 {
2201  size_type idx = static_cast<size_type>(pos - cbegin());
2202  size_type gap_size = static_cast<size_type>(std::distance(first, last));
2203 
2204  pool_base pb = get_pool();
2205  transaction::run(pb, [&] {
2206  insert_gap(idx, gap_size);
2207  for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2208  get(i) = *first;
2209  });
2210 
2211  return iterator(this, idx);
2212 }
2213 
2240 template <typename T, typename Segment, typename Policy>
2243  std::initializer_list<T> ilist)
2244 {
2245  return insert(pos, ilist.begin(), ilist.end());
2246 }
2247 
2276 template <typename T, typename Segment, typename Policy>
2277 template <class... Args>
2280 {
2281  size_type idx = static_cast<size_type>(pos - cbegin());
2282 
2283  pool_base pb = get_pool();
2284  transaction::run(pb, [&] {
2285  detail::temp_value<value_type,
2286  noexcept(T(std::forward<Args>(args)...))>
2287  tmp(std::forward<Args>(args)...);
2288  insert_gap(idx, 1);
2289  get(idx) = std::move(tmp.get());
2290  });
2291 
2292  return iterator(this, idx);
2293 }
2294 
2319 template <typename T, typename Segment, typename Policy>
2320 template <class... Args>
2321 typename segment_vector<T, Segment, Policy>::reference
2323 {
2324  assert(size() < max_size());
2325 
2326  pool_base pb = get_pool();
2327  transaction::run(pb, [&] {
2328  if (size() == capacity())
2329  internal_reserve(capacity() + 1);
2330 
2331  size_type segment = policy::get_segment(size());
2332  _data[segment].emplace_back(std::forward<Args>(args)...);
2333  });
2334 
2335  return back();
2336 }
2337 
2359 template <typename T, typename Segment, typename Policy>
2362 {
2363  return erase(pos, pos + 1);
2364 }
2365 
2390 template <typename T, typename Segment, typename Policy>
2393  const_iterator last)
2394 {
2395  size_type count = static_cast<size_type>(std::distance(first, last));
2396  size_type idx = static_cast<size_type>(first - cbegin());
2397 
2398  if (count == 0)
2399  return iterator(this, idx);
2400 
2401  pool_base pb = get_pool();
2402  transaction::run(pb, [&] {
2403  size_type _size = size();
2404 
2405  snapshot_data(idx, _size);
2406 
2407  /* Moving after-range elements to the place of deleted
2408  */
2409  iterator dest = iterator(this, idx);
2410  iterator begin = iterator(this, idx + count);
2411  iterator end = iterator(this, _size);
2412  std::move(begin, end, dest);
2413 
2414  /* Clearing the range where the elements were moved from
2415  */
2416  size_type middle = policy::get_segment(_size - count);
2417  size_type last = policy::get_segment(_size - 1);
2418  size_type middle_size = policy::index_in_segment(_size - count);
2419  for (size_type s = last; s > middle; --s)
2420  _data[s].clear();
2421  _data[middle].resize(middle_size);
2422 
2423  _segments_used = middle + 1;
2424  });
2425 
2426  assert(segment_capacity_validation());
2427 
2428  return iterator(this, idx);
2429 }
2430 
2449 template <typename T, typename Segment, typename Policy>
2450 void
2452 {
2453  emplace_back(value);
2454 }
2455 
2474 template <typename T, typename Segment, typename Policy>
2475 void
2477 {
2478  emplace_back(std::move(value));
2479 }
2480 
2494 template <typename T, typename Segment, typename Policy>
2495 void
2497 {
2498  if (empty())
2499  return;
2500 
2501  pool_base pb = get_pool();
2502  transaction::run(pb, [&] { shrink(size() - 1); });
2503  assert(segment_capacity_validation());
2504 }
2505 
2529 template <typename T, typename Segment, typename Policy>
2530 void
2532 {
2533  pool_base pb = get_pool();
2534  transaction::run(pb, [&] {
2535  size_type _size = size();
2536  if (count < _size)
2537  shrink(count);
2538  else {
2539  if (capacity() < count)
2540  internal_reserve(count);
2541  construct(_size, count - _size);
2542  }
2543  });
2544  assert(segment_capacity_validation());
2545 }
2546 
2571 template <typename T, typename Segment, typename Policy>
2572 void
2574  const value_type &value)
2575 {
2576  pool_base pb = get_pool();
2577  transaction::run(pb, [&] {
2578  size_type _size = size();
2579  if (count < _size)
2580  shrink(count);
2581  else {
2582  if (capacity() < count)
2583  internal_reserve(count);
2584  construct(_size, count - _size, value);
2585  }
2586  });
2587  assert(segment_capacity_validation());
2588 }
2589 
2593 template <typename T, typename Segment, typename Policy>
2594 void
2596 {
2597  pool_base pb = get_pool();
2598  transaction::run(pb, [&] {
2599  _data.swap(other._data);
2600  std::swap(_segments_used, other._segments_used);
2601  });
2602 }
2603 
2620 template <typename T, typename Segment, typename Policy>
2621 void
2623 {
2624  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2625 
2626  if (new_capacity > max_size())
2627  throw std::length_error("New capacity exceeds max size.");
2628 
2629  if (new_capacity == 0)
2630  return;
2631 
2632  size_type old_idx = policy::get_segment(capacity());
2633  size_type new_idx = policy::get_segment(new_capacity - 1);
2634  storage::resize(_data, new_idx + 1);
2635  for (size_type i = old_idx; i <= new_idx; ++i) {
2636  size_type segment_capacity = policy::segment_size(i);
2637  _data[i].reserve(segment_capacity);
2638  }
2639  _segments_used = new_idx + 1;
2640 
2641  assert(segment_capacity_validation());
2642 }
2643 
2670 template <typename T, typename Segment, typename Policy>
2671 template <typename... Args>
2672 void
2673 segment_vector<T, Segment, Policy>::construct(size_type idx, size_type count,
2674  Args &&... args)
2675 {
2676  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2677  assert(_segments_used - 1 >= policy::get_segment(size() + count - 1));
2678 
2679  for (size_type i = idx; i < idx + count; ++i) {
2680  size_type segment = policy::get_segment(i);
2681  _data[segment].emplace_back(std::forward<Args>(args)...);
2682  }
2683 }
2684 
2715 template <typename T, typename Segment, typename Policy>
2716 template <typename InputIt,
2717  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2718  InputIt>::type *>
2719 void
2721  InputIt first, InputIt last)
2722 {
2723  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2724  size_type count = static_cast<size_type>(std::distance(first, last));
2725  assert(count >= 0);
2726  assert(_segments_used - 1 >= policy::get_segment(size() + count - 1));
2727 
2728  for (size_type i = idx; i < idx + count; ++i, ++first) {
2729  size_type segment = policy::get_segment(i);
2730  _data[segment].emplace_back(*first);
2731  }
2732 }
2733 
2755 template <typename T, typename Segment, typename Policy>
2756 void
2757 segment_vector<T, Segment, Policy>::insert_gap(size_type idx, size_type count)
2758 {
2759  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2760 
2761  size_type _size = size();
2762 
2763  if (capacity() < _size + count)
2764  internal_reserve(_size + count);
2765 
2766  iterator dest = iterator(this, _size + count);
2767  iterator begin = iterator(this, idx);
2768  iterator end = iterator(this, _size);
2769 
2770  snapshot_data(idx, _size);
2771 
2772  resize(_size + count);
2773  std::move_backward(begin, end, dest);
2774 
2775  assert(segment_capacity_validation());
2776 }
2777 
2797 template <typename T, typename Segment, typename Policy>
2798 void
2800 {
2801  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2802  assert(size_new <= size());
2803 
2804  snapshot_data(size_new, size());
2805 
2806  size_type begin = policy::get_segment(size() - 1);
2807  size_type end = policy::get_segment(size_new);
2808  for (; begin > end; --begin) {
2809  _data[begin].clear();
2810  }
2811  size_type residue = policy::index_in_segment(size_new);
2812  _data[end].erase(_data[end].cbegin() + residue, _data[end].cend());
2813 }
2814 
2822 template <typename T, typename Segment, typename Policy>
2823 pool_base
2825 {
2826  auto pop = pmemobj_pool_by_ptr(this);
2827  assert(pop != nullptr);
2828  return pool_base(pop);
2829 }
2830 
2840 template <typename T, typename Segment, typename Policy>
2841 void
2843  size_type last)
2844 {
2845  if (first == last)
2846  return;
2847 
2848  size_type segment = policy::get_segment(first);
2849  size_type end = policy::get_segment(last - 1);
2850  size_type count = policy::segment_top(segment + 1) - first;
2851 
2852  while (segment != end) {
2853  detail::conditional_add_to_tx(&cget(first), count,
2854  POBJ_XADD_ASSUME_INITIALIZED);
2855  first = policy::segment_top(++segment);
2856  count = policy::segment_size(segment);
2857  }
2858  detail::conditional_add_to_tx(&cget(first), last - first,
2859  POBJ_XADD_ASSUME_INITIALIZED);
2860 }
2861 
2867 template <typename T, typename Segment, typename Policy>
2868 typename segment_vector<T, Segment, Policy>::reference
2870 {
2871  size_type s_idx = policy::get_segment(n);
2872  size_type local_idx = policy::index_in_segment(n);
2873 
2874  return _data[s_idx][local_idx];
2875 }
2876 
2882 template <typename T, typename Segment, typename Policy>
2883 typename segment_vector<T, Segment, Policy>::const_reference
2885 {
2886  size_type s_idx = policy::get_segment(n);
2887  size_type local_idx = policy::index_in_segment(n);
2888 
2889  return _data[s_idx][local_idx];
2890 }
2891 
2897 template <typename T, typename Segment, typename Policy>
2898 typename segment_vector<T, Segment, Policy>::const_reference
2900 {
2901  size_type s_idx = policy::get_segment(n);
2902  size_type local_idx = policy::index_in_segment(n);
2903 
2904  return _data[s_idx][local_idx];
2905 }
2906 
2914 template <typename T, typename Segment, typename Policy>
2915 bool
2917 {
2918  for (size_type i = 0; i < _segments_used; ++i)
2919  if (_data.const_at(i).capacity() != policy::segment_size(i))
2920  return false;
2921  return true;
2922 }
2923 
2930 template <typename T, typename Segment, typename Policy>
2931 void
2934 {
2935  lhs.swap(rhs);
2936 }
2937 
2952 template <typename T, typename Segment, typename Policy>
2953 bool
2956 {
2957  return lhs.size() == rhs.size() &&
2958  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2959 }
2960 
2976 template <typename T, typename Segment, typename Policy>
2977 bool
2980 {
2981  return !(lhs == rhs);
2982 }
2983 
2996 template <typename T, typename Segment, typename Policy>
2997 bool
2998 operator<(const segment_vector<T, Segment, Policy> &lhs,
3000 {
3001  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
3002  rhs.end());
3003 }
3004 
3017 template <typename T, typename Segment, typename Policy>
3018 bool
3019 operator<=(const segment_vector<T, Segment, Policy> &lhs,
3021 {
3022  return !(rhs < lhs);
3023 }
3024 
3037 template <typename T, typename Segment, typename Policy>
3038 bool
3041 {
3042  return rhs < lhs;
3043 }
3044 
3057 template <typename T, typename Segment, typename Policy>
3058 bool
3061 {
3062  return !(lhs < rhs);
3063 }
3064 
3078 template <typename T, typename Segment, typename Policy>
3079 bool
3081  const std::vector<T> &rhs)
3082 {
3083  return lhs.size() == rhs.size() &&
3084  std::equal(lhs.begin(), lhs.end(), rhs.begin());
3085 }
3086 
3100 template <typename T, typename Segment, typename Policy>
3101 bool
3103  const std::vector<T> &rhs)
3104 {
3105  return !(lhs == rhs);
3106 }
3107 
3119 template <typename T, typename Segment, typename Policy>
3120 bool
3121 operator<(const segment_vector<T, Segment, Policy> &lhs,
3122  const std::vector<T> &rhs)
3123 {
3124  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
3125  rhs.end());
3126 }
3127 
3139 template <typename T, typename Segment, typename Policy>
3140 bool
3141 operator<=(const segment_vector<T, Segment, Policy> &lhs,
3142  const std::vector<T> &rhs)
3143 {
3144  return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
3145  lhs.begin(), lhs.end()));
3146 }
3147 
3160 template <typename T, typename Segment, typename Policy>
3161 bool
3163  const std::vector<T> &rhs)
3164 {
3165  return !(lhs <= rhs);
3166 }
3167 
3179 template <typename T, typename Segment, typename Policy>
3180 bool
3182  const std::vector<T> &rhs)
3183 {
3184  return !(lhs < rhs);
3185 }
3186 
3200 template <typename T, typename Segment, typename Policy>
3201 bool
3202 operator==(const std::vector<T> &lhs,
3204 {
3205  return rhs == lhs;
3206 }
3207 
3221 template <typename T, typename Segment, typename Policy>
3222 bool
3223 operator!=(const std::vector<T> &lhs,
3225 {
3226  return !(lhs == rhs);
3227 }
3228 
3240 template <typename T, typename Segment, typename Policy>
3241 bool
3242 operator<(const std::vector<T> &lhs,
3244 {
3245  return rhs > lhs;
3246 }
3247 
3259 template <typename T, typename Segment, typename Policy>
3260 bool
3261 operator<=(const std::vector<T> &lhs,
3263 {
3264  return !(rhs < lhs);
3265 }
3266 
3279 template <typename T, typename Segment, typename Policy>
3280 bool
3281 operator>(const std::vector<T> &lhs,
3283 {
3284  return rhs < lhs;
3285 }
3286 
3298 template <typename T, typename Segment, typename Policy>
3299 bool
3300 operator>=(const std::vector<T> &lhs,
3302 {
3303  return !(lhs < rhs);
3304 }
3305 
3306 } /* namespace experimental */
3307 } /* namespace obj */
3308 } /* namespace pmem */
3309 
3310 #endif /* LIBPMEMOBJ_SEGMENT_VECTOR_HPP */
void construct_range(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: segment_vector.hpp:2720
iterator insert(const_iterator pos, const T &value)
Inserts value before pos in the container transactionally.
Definition: segment_vector.hpp:2074
size_type capacity() const noexcept
Definition: segment_vector.hpp:1970
reference get(size_type n)
Private helper function.
Definition: segment_vector.hpp:2869
bool operator>(const segment_iterator< Container, C > &rhs)
Greater operator.
Definition: segment_vector.hpp:394
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:913
reference front()
Access the first element and add this element to a transaction.
Definition: segment_vector.hpp:1591
pool_base get_pool() const noexcept
Private helper function.
Definition: segment_vector.hpp:2824
const_reference cback() const
Access the last element.
Definition: segment_vector.hpp:1666
Persistent_ptr transactional allocation functions for objects.
pmem::obj::array< T, N >::reverse_iterator rend(pmem::obj::array< T, N > &a)
Non-member rend.
Definition: array.hpp:893
pmem::obj::array< T, N >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:823
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: segment_vector.hpp:1747
segment_iterator & operator--()
Prefix decrement.
Definition: segment_vector.hpp:251
The non-template pool base class.
Definition: pool.hpp:67
temp_value template class for caching objects.
~segment_vector()
Destructor.
Definition: segment_vector.hpp:1474
Segment table is a data type with a vector-like interface The difference is that it does not do reall...
Definition: segment_vector.hpp:710
iterator begin()
Returns an iterator to the beginning.
Definition: segment_vector.hpp:1678
void free_data()
Clears the content of a segment_vector and frees all allocated persistent memory for data transaction...
Definition: segment_vector.hpp:2039
void pop_back()
Removes the last element of the container transactionally.
Definition: segment_vector.hpp:2496
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: segment_vector.hpp:1908
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:56
segment_vector_internal::fixed_size_policy< pmem::obj::array< SegmentType, 255 >, SegmentSize > fixed_size_array_policy
XXX: In case of array of segments with fixed segments size we can allocate as much memory as we want...
Definition: segment_vector.hpp:671
void shrink_to_fit()
Requests transactional removal of unused capacity.
Definition: segment_vector.hpp:1990
segment_iterator & operator-=(difference_type idx)
Random access decrementing with assignment.
Definition: segment_vector.hpp:290
C++ pmemobj transactions.
Convenience extensions for the resides on pmem property template.
const_reference cfront() const
Access the first element.
Definition: segment_vector.hpp:1620
void construct(size_type idx, size_type count, Args &&... args)
Private helper function.
Definition: segment_vector.hpp:2673
void push_back(const T &value)
Appends the given element value to the end of the container transactionally.
Definition: segment_vector.hpp:2451
Functions for destroying arrays.
Commonly used functionality.
iterator end()
Returns an iterator to past the end.
Definition: segment_vector.hpp:1719
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:813
Iterator for segment_vector Since a constant iterator differs only in the type of references and poin...
Definition: segment_vector.hpp:71
void shrink(size_type size_new)
Private helper function.
Definition: segment_vector.hpp:2799
segment_iterator & operator+=(difference_type idx)
Random access incrementing with assignment.
Definition: segment_vector.hpp:238
void reserve(size_type capacity_new)
Increases the capacity of the segment_vector to capacity_new transactionally.
Definition: segment_vector.hpp:1955
iterator emplace(const_iterator pos, Args &&... args)
Inserts a new element into the container directly before pos.
Definition: segment_vector.hpp:2279
void swap(segment_vector &other)
Exchanges the contents of the container with other transactionally.
Definition: segment_vector.hpp:2595
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1788
bool operator==(const segment_iterator< Container, C > &rhs)
Compare methods Template parameter is needed to enable this methods work with non-constant and consta...
Definition: segment_vector.hpp:335
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: segment_vector.hpp:1537
slice< iterator > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: segment_vector.hpp:1849
void assign(size_type count, const_reference value)
Replaces the contents with count copies of value value transactionally.
Definition: segment_vector.hpp:1279
bool operator>=(const segment_iterator< Container, C > &rhs)
Greater or equal operator.
Definition: segment_vector.hpp:440
reference at(size_type n)
Access element at specific index with bounds checking and add it to a transaction.
Definition: segment_vector.hpp:1494
Array container with std::array compatible interface.
reference emplace_back(Args &&... args)
Appends a new element to the end of the container transactionally.
Definition: segment_vector.hpp:2322
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:853
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:75
constexpr size_type max_size() const noexcept
Definition: segment_vector.hpp:1932
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:833
const_reference cget(size_type n) const
Private helper function.
Definition: segment_vector.hpp:2899
segment_iterator & operator++()
Prefix increment.
Definition: segment_vector.hpp:199
Template class for caching objects based on constructor&#39;s variadic template arguments and LIBPMEMOBJ_...
Definition: temp_value.hpp:64
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: segment_vector.hpp:1760
pmem::obj::vector - persistent container with std::vector compatible interface.
Definition: vector.hpp:69
void internal_reserve(size_type new_capacity)
Private helper method.
Definition: segment_vector.hpp:2622
reference operator*() const
Indirection (dereference).
Definition: segment_vector.hpp:453
segment_vector & operator=(const segment_vector &other)
Copy assignment operator.
Definition: segment_vector.hpp:1176
bool segment_capacity_validation() const
Private helper function.
Definition: segment_vector.hpp:2916
segment_iterator operator-(difference_type idx) const
Random access decrementing.
Definition: segment_vector.hpp:278
Vector container with std::vector compatible interface.
Commonly used SFINAE helpers.
Persistent smart pointer.
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: segment_vector.hpp:1706
size_type size() const noexcept
Definition: segment_vector.hpp:1918
iterator erase(const_iterator pos)
Removes the element at pos.
Definition: segment_vector.hpp:2361
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1829
segment_vector()
Default constructor.
Definition: segment_vector.hpp:948
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:793
segment_iterator operator+(difference_type idx) const
Random access incrementing.
Definition: segment_vector.hpp:226
void insert_gap(size_type idx, size_type count)
Private helper function.
Definition: segment_vector.hpp:2757
reference back()
Access the last element and add this element to a transaction.
Definition: segment_vector.hpp:1635
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: segment_vector.hpp:1801
bool operator<(const segment_iterator< Container, C > &rhs)
Less operator.
Definition: segment_vector.hpp:371
bool operator!=(const segment_iterator< Container, C > &rhs)
Not equal operator.
Definition: segment_vector.hpp:352
pointer operator->() const
Member access.
Definition: segment_vector.hpp:463
void clear()
Clears the content of a segment_vector transactionally.
Definition: segment_vector.hpp:2018
A persistent version of concurrent hash map implementation Ref: https://arxiv.org/abs/1509.02235.
Definition: allocation_flag.hpp:43
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: segment_vector.hpp:1557
pmem::obj::array< T, N >::reverse_iterator rbegin(pmem::obj::array< T, N > &a)
Non-member rbegin.
Definition: array.hpp:873
segment_iterator() noexcept
Default constructor.
Definition: segment_vector.hpp:155
void snapshot_data(size_type idx_first, size_type idx_last)
Private helper function.
Definition: segment_vector.hpp:2842
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:803
bool operator<=(const segment_iterator< Container, C > &rhs)
Less or equal operator.
Definition: segment_vector.hpp:417
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: segment_vector.hpp:1893
void resize(size_type count)
Resizes the container to count elements transactionally.
Definition: segment_vector.hpp:2531
pmem::obj::array - persistent container with std::array compatible interface.
Definition: array.hpp:74
static void run(pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:403