PMDK C++ bindings  1.8.2
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 */
117  segment_iterator operator+(difference_type idx) const;
118  segment_iterator &operator+=(difference_type idx);
121  segment_iterator operator-(difference_type idx) const;
122  segment_iterator &operator-=(difference_type idx);
123  template <bool C>
124  difference_type
125  operator+(const segment_iterator<Container, C> &rhs) const;
126  template <bool C>
127  difference_type
128  operator-(const segment_iterator<Container, C> &rhs) const;
129 
135  template <bool C>
136  bool operator==(const segment_iterator<Container, C> &rhs) const;
137  template <bool C>
138  bool operator!=(const segment_iterator<Container, C> &rhs) const;
139  template <bool C>
140  bool operator<(const segment_iterator<Container, C> &rhs) const;
141  template <bool C>
142  bool operator>(const segment_iterator<Container, C> &rhs) const;
143  template <bool C>
144  bool operator<=(const segment_iterator<Container, C> &rhs) const;
145  template <bool C>
146  bool operator>=(const segment_iterator<Container, C> &rhs) const;
147 
148  /* Access methods */
149  reference operator*() const;
150  pointer operator->() const;
151 };
152 
156 template <typename Container, bool is_const>
158  : table(nullptr), index()
159 {
160 }
161 
166 template <typename Container, bool is_const>
168  size_type idx) noexcept
169  : table(tab), index(idx)
170 {
171 }
172 
177 template <typename Container, bool is_const>
179  const segment_iterator &other)
180  : table(other.table), index(other.index)
181 {
182 }
183 
185 template <typename Container, bool is_const>
186 template <typename U, typename>
189  : table(other.table), index(other.index)
190 {
191 }
192 
198 template <typename Container, bool is_const>
201 {
202  ++index;
203  return *this;
204 }
205 
211 template <typename Container, bool is_const>
214 {
215  auto iterator = *this;
216  ++*this;
217  return iterator;
218 }
219 
225 template <typename Container, bool is_const>
228 {
229  return segment_iterator(table, index + static_cast<size_type>(idx));
230 }
231 
237 template <typename Container, bool is_const>
240 {
241  index += static_cast<size_type>(idx);
242  return *this;
243 }
244 
250 template <typename Container, bool is_const>
253 {
254  --index;
255  return *this;
256 }
257 
263 template <typename Container, bool is_const>
266 {
267  auto iterator = *this;
268  --*this;
269  return iterator;
270 }
271 
277 template <typename Container, bool is_const>
280 {
281  return segment_iterator(table, index - static_cast<size_type>(idx));
282 }
283 
289 template <typename Container, bool is_const>
292 {
293  index -= static_cast<size_type>(idx);
294  return *this;
295 }
296 
302 template <typename Container, bool is_const>
303 template <bool C>
304 typename segment_iterator<Container, is_const>::difference_type
307 {
308  return static_cast<difference_type>(index + rhs.index);
309 }
310 
316 template <typename Container, bool is_const>
317 template <bool C>
318 typename segment_iterator<Container, is_const>::difference_type
321 {
322  return static_cast<difference_type>(index - rhs.index);
323 }
324 
332 template <typename Container, bool is_const>
333 template <bool C>
334 bool
337 {
338  return (table == rhs.table) && (index == rhs.index);
339 }
340 
349 template <typename Container, bool is_const>
350 template <bool C>
351 bool
354 {
355  return (table != rhs.table) || (index != rhs.index);
356 }
357 
368 template <typename Container, bool is_const>
369 template <bool C>
370 bool
373 {
374  if (table != rhs.table)
375  throw std::invalid_argument("segment_iterator::operator<");
376 
377  return index < rhs.index;
378 }
379 
391 template <typename Container, bool is_const>
392 template <bool C>
393 bool
396 {
397  if (table != rhs.table)
398  throw std::invalid_argument("segment_iterator::operator<");
399 
400  return index > rhs.index;
401 }
402 
414 template <typename Container, bool is_const>
415 template <bool C>
416 bool
419 {
420  if (table != rhs.table)
421  throw std::invalid_argument("segment_iterator::operator<");
422 
423  return index <= rhs.index;
424 }
425 
437 template <typename Container, bool is_const>
438 template <bool C>
439 bool
442 {
443  if (table != rhs.table)
444  throw std::invalid_argument("segment_iterator::operator<");
445 
446  return index >= rhs.index;
447 }
448 
452 template <typename Container, bool is_const>
453 typename segment_iterator<Container, is_const>::reference
455 {
456  return table->operator[](index);
457 }
458 
462 template <typename Container, bool is_const>
463 typename segment_iterator<Container, is_const>::pointer
465 {
466  return &operator*();
467 }
468 
469 template <typename Container>
470 using resize_method =
471  decltype(std::declval<Container>().resize(std::declval<size_t>()));
472 
473 template <typename Container>
474 using container_has_resize = detail::supports<Container, resize_method>;
475 
476 template <typename Container, bool = container_has_resize<Container>::value>
477 struct segment_vector_resize {
478  using segment_vector_type = Container;
479 
480  static void
481  resize(segment_vector_type &c, size_t n)
482  {
483  c.resize(n);
484  }
485 };
486 
487 template <typename Container>
488 struct segment_vector_resize<Container, false> {
489  using segment_vector_type = Container;
490 
491  static void
492  resize(segment_vector_type &c, size_t n)
493  {
494  }
495 };
496 
497 template <typename SegmentVectorType, size_t SegmentSize>
498 class fixed_size_policy {
499 public:
500  /* Traits */
501  using segment_vector_type = SegmentVectorType;
502  using segment_type = typename segment_vector_type::value_type;
503  using value_type = typename segment_type::value_type;
504  using size_type = std::size_t;
505 
506  using segment_vector_resize_type =
507  segment_vector_resize<segment_vector_type>;
508 
509  static constexpr size_type Size = SegmentSize;
510 
511  static void
512  resize(segment_vector_type &c, size_type n)
513  {
514  segment_vector_resize_type::resize(c, n);
515  }
516 
522  static size_type
523  get_segment(size_type index)
524  {
525  return index / Size;
526  }
532  static size_type
533  segment_top(size_type segment_index)
534  {
535  return segment_index * Size;
536  }
542  static size_type
543  segment_size(size_type segment_index)
544  {
545  return Size;
546  }
552  static size_type
553  index_in_segment(size_type index)
554  {
555  return index % Size;
556  }
557 
561  static size_type
562  max_size(const SegmentVectorType &seg_storage)
563  {
564  return seg_storage.max_size() * SegmentSize;
565  }
566 
570  static size_type
571  capacity(size_type segment_index)
572  {
573  return (segment_index + 1) * Size;
574  }
575 };
576 
577 template <typename SegmentVectorType>
578 class exponential_size_policy {
579 public:
580  /* Traits */
581  using segment_vector_type = SegmentVectorType;
582  using segment_type = typename segment_vector_type::value_type;
583  using value_type = typename segment_type::value_type;
584  using size_type = std::size_t;
585 
586  using segment_vector_resize_type =
587  segment_vector_resize<segment_vector_type>;
588 
589  static void
590  resize(segment_vector_type &c, size_type n)
591  {
592  segment_vector_resize_type::resize(c, n);
593  }
594 
600  static size_type
601  get_segment(size_type index)
602  {
603  return static_cast<size_type>(detail::Log2(index | 1));
604  }
610  static size_type
611  segment_top(size_type segment_index)
612  {
613  return (size_type(1) << segment_index) & ~size_type(1);
614  }
620  static size_type
621  segment_size(size_type segment_index)
622  {
623  return (segment_index == 0) ? 2 : segment_top(segment_index);
624  }
630  static size_type
631  index_in_segment(size_type index)
632  {
633  return index - segment_top(get_segment(index));
634  }
635 
639  static size_t
640  max_size(const SegmentVectorType &)
641  {
642  return segment_size(get_segment(PMEMOBJ_MAX_ALLOC_SIZE /
643  sizeof(value_type)) +
644  1);
645  }
646 
650  static size_type
651  capacity(size_type segment_index)
652  {
653  if (segment_index == 0)
654  return 2;
655  return segment_size(segment_index) * 2;
656  }
657 };
658 
659 } /* segment_vector_internal namespace */
660 
661 template <typename SegmentType>
662 using exponential_size_array_policy =
663  segment_vector_internal::exponential_size_policy<
665 
670 template <typename SegmentType, size_t SegmentSize>
671 using fixed_size_array_policy = segment_vector_internal::fixed_size_policy<
673 
674 template <typename SegmentType, size_t SegmentSize>
675 using fixed_size_vector_policy = segment_vector_internal::fixed_size_policy<
676  pmem::obj::vector<SegmentType>, SegmentSize>;
677 
678 template <typename SegmentType>
679 using exponential_size_vector_policy =
680  segment_vector_internal::exponential_size_policy<
682 
709 template <typename T, typename Segment = pmem::obj::vector<T>,
710  typename Policy = exponential_size_array_policy<Segment>>
712 public:
713  /* Specific traits*/
714  using policy_type = Policy;
715  using segment_type = typename policy_type::segment_type;
716  using segment_vector_type = typename policy_type::segment_vector_type;
717  /* Simple access to methods */
718  using policy = policy_type;
719  using storage = policy_type;
720 
721  /* Traits */
722  using value_type = T;
723  using size_type = std::size_t;
724  using difference_type = std::ptrdiff_t;
725  using reference = value_type &;
726  using const_reference = const value_type &;
727  using pointer = value_type *;
728  using const_pointer = const value_type *;
729  using iterator =
731  false>;
732  using const_iterator =
734  using reverse_iterator = std::reverse_iterator<iterator>;
735  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
736 
737  /* Constructors */
738  segment_vector();
739  segment_vector(size_type count, const value_type &value);
740  explicit segment_vector(size_type count);
741  template <typename InputIt,
742  typename std::enable_if<
744  InputIt>::type * = nullptr>
745  segment_vector(InputIt first, InputIt last);
746  segment_vector(const segment_vector &other);
748  segment_vector(std::initializer_list<T> init);
749  segment_vector(const std::vector<T> &other);
750 
751  /* Assign operators */
752  segment_vector &operator=(const segment_vector &other);
754  segment_vector &operator=(std::initializer_list<T> ilist);
755  segment_vector &operator=(const std::vector<T> &other);
756 
757  /* Assign methods */
758  void assign(size_type count, const_reference value);
759  template <typename InputIt,
760  typename std::enable_if<
762  InputIt>::type * = nullptr>
763  void assign(InputIt first, InputIt last);
764  void assign(std::initializer_list<T> ilist);
765  void assign(const segment_vector &other);
766  void assign(segment_vector &&other);
767  void assign(const std::vector<T> &other);
768 
769  /* Destructor */
770  ~segment_vector();
771 
772  /* Element access */
773  reference at(size_type n);
774  const_reference at(size_type n) const;
775  const_reference const_at(size_type n) const;
776  reference operator[](size_type n);
777  const_reference operator[](size_type n) const;
778  reference front();
779  const_reference front() const;
780  const_reference cfront() const;
781  reference back();
782  const_reference back() const;
783  const_reference cback() const;
784 
785  /* Iterators */
786  iterator begin();
787  const_iterator begin() const noexcept;
788  const_iterator cbegin() const noexcept;
789  iterator end();
790  const_iterator end() const noexcept;
791  const_iterator cend() const noexcept;
792  reverse_iterator rbegin();
793  const_reverse_iterator rbegin() const noexcept;
794  const_reverse_iterator crbegin() const noexcept;
795  reverse_iterator rend();
796  const_reverse_iterator rend() const noexcept;
797  const_reverse_iterator crend() const noexcept;
798 
799  /* Range */
800  slice<iterator> range(size_type start, size_type n);
801  slice<const_iterator> range(size_type start, size_type n) const;
802  slice<const_iterator> crange(size_type start, size_type n) const;
803 
804  /* Capacity */
805  constexpr bool empty() const noexcept;
806  size_type size() const noexcept;
807  constexpr size_type max_size() const noexcept;
808  void reserve(size_type capacity_new);
809  size_type capacity() const noexcept;
810  void shrink_to_fit();
811 
812  /* Modifiers */
813  void clear();
814  void free_data();
815  iterator insert(const_iterator pos, const T &value);
816  iterator insert(const_iterator pos, T &&value);
817  iterator insert(const_iterator pos, size_type count, const T &value);
818  template <typename InputIt,
819  typename std::enable_if<
821  InputIt>::type * = nullptr>
822  iterator insert(const_iterator pos, InputIt first, InputIt last);
823  iterator insert(const_iterator pos, std::initializer_list<T> ilist);
824  template <class... Args>
825  iterator emplace(const_iterator pos, Args &&... args);
826  template <class... Args>
827  reference emplace_back(Args &&... args);
830  void push_back(const T &value);
831  void push_back(T &&value);
832  void pop_back();
833  void resize(size_type count);
834  void resize(size_type count, const value_type &value);
835  void swap(segment_vector &other);
836 
837 private:
838  /* Helper functions */
839  void internal_reserve(size_type new_capacity);
840  template <typename... Args>
841  void construct(size_type idx, size_type count, Args &&... args);
842  template <typename InputIt,
843  typename std::enable_if<
845  InputIt>::type * = nullptr>
846  void construct_range(size_type idx, InputIt first, InputIt last);
847  void insert_gap(size_type idx, size_type count);
848  void shrink(size_type size_new);
849  pool_base get_pool() const noexcept;
850  void snapshot_data(size_type idx_first, size_type idx_last);
851 
852  /* Data structure specific helper functions */
853  reference get(size_type n);
854  const_reference get(size_type n) const;
855  const_reference cget(size_type n) const;
856  bool segment_capacity_validation() const;
857 
858  /* Number of segments that currently enabled */
859  p<size_type> _segments_used = 0;
860  /* Segments storage */
861  segment_vector_type _data;
862 };
863 
864 /* Non-member swap */
865 template <typename T, typename Segment, typename Policy>
868 
869 /*
870  * Comparison operators between
871  * pmem::obj::experimental::segment_vector<T, Segment, Policy> and
872  * pmem::obj::experimental::segment_vector<T, Segment, Policy>
873  */
874 template <typename T, typename Segment, typename Policy>
877 template <typename T, typename Segment, typename Policy>
880 template <typename T, typename Segment, typename Policy>
883 template <typename T, typename Segment, typename Policy>
886 template <typename T, typename Segment, typename Policy>
889 template <typename T, typename Segment, typename Policy>
892 
893 /*
894  * Comparison operators between
895  * pmem::obj::experimental::segment_vector<T, Segment, Policy> and
896  * std::vector<T>
897  */
898 template <typename T, typename Segment, typename Policy>
900  const std::vector<T> &rhs);
901 template <typename T, typename Segment, typename Policy>
903  const std::vector<T> &rhs);
904 template <typename T, typename Segment, typename Policy>
906  const std::vector<T> &rhs);
907 template <typename T, typename Segment, typename Policy>
909  const std::vector<T> &rhs);
910 template <typename T, typename Segment, typename Policy>
912  const std::vector<T> &rhs);
913 template <typename T, typename Segment, typename Policy>
915  const std::vector<T> &rhs);
916 
917 /*
918  * Comparison operators between std::vector<T> and
919  * pmem::obj::experimental::segment_vector<T, Segment, Policy>
920  */
921 template <typename T, typename Segment, typename Policy>
922 bool operator==(const std::vector<T> &lhs,
924 template <typename T, typename Segment, typename Policy>
925 bool operator!=(const std::vector<T> &lhs,
927 template <typename T, typename Segment, typename Policy>
928 bool operator<(const std::vector<T> &lhs,
930 template <typename T, typename Segment, typename Policy>
931 bool operator<=(const std::vector<T> &lhs,
933 template <typename T, typename Segment, typename Policy>
934 bool operator>(const std::vector<T> &lhs,
936 template <typename T, typename Segment, typename Policy>
937 bool operator>=(const std::vector<T> &lhs,
939 
948 template <typename T, typename Segment, typename Policy>
950 {
951 }
952 
975 template <typename T, typename Segment, typename Policy>
977  const value_type &value)
978 {
979  internal_reserve(count);
980  construct(0, count, value);
981 }
982 
1004 template <typename T, typename Segment, typename Policy>
1006 {
1007  internal_reserve(count);
1008  construct(0, count);
1009 }
1010 
1037 template <typename T, typename Segment, typename Policy>
1038 template <typename InputIt,
1039  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1040  InputIt>::type *>
1042 {
1043  internal_reserve(static_cast<size_type>(std::distance(first, last)));
1044  construct_range(0, first, last);
1045 }
1046 
1068 template <typename T, typename Segment, typename Policy>
1070 {
1071  internal_reserve(other.capacity());
1072  construct_range(0, other.cbegin(), other.cend());
1073 }
1074 
1095 template <typename T, typename Segment, typename Policy>
1097 {
1098  _data = std::move(other._data);
1099  _segments_used = other._segments_used;
1100  other._segments_used = 0;
1101 }
1102 
1124 template <typename T, typename Segment, typename Policy>
1126  std::initializer_list<T> init)
1127  : segment_vector(init.begin(), init.end())
1128 {
1129 }
1130 
1152 template <typename T, typename Segment, typename Policy>
1154  : segment_vector(other.cbegin(), other.cend())
1155 {
1156 }
1157 
1175 template <typename T, typename Segment, typename Policy>
1178 {
1179  assign(other);
1180  return *this;
1181 }
1182 
1198 template <typename T, typename Segment, typename Policy>
1201 {
1202  assign(std::move(other));
1203  return *this;
1204 }
1205 
1223 template <typename T, typename Segment, typename Policy>
1225 segment_vector<T, Segment, Policy>::operator=(std::initializer_list<T> ilist)
1226 {
1227  assign(ilist.begin(), ilist.end());
1228  return *this;
1229 }
1230 
1248 template <typename T, typename Segment, typename Policy>
1251 {
1252  assign(other);
1253  return *this;
1254 }
1255 
1278 template <typename T, typename Segment, typename Policy>
1279 void
1281  const_reference value)
1282 {
1283  if (count > max_size())
1284  throw std::length_error("Assignable range exceeds max size.");
1285 
1286  pool_base pb = get_pool();
1287  transaction::run(pb, [&] {
1288  if (count > capacity())
1289  internal_reserve(count);
1290  else if (count < size())
1291  shrink(count);
1292 
1293  size_type end = policy::get_segment(count - 1);
1294  for (size_type i = 0; i < end; ++i)
1295  _data[i].assign(policy::segment_size(i), value);
1296  _data[end].assign(count - policy::segment_top(end), value);
1297 
1298  _segments_used = end + 1;
1299  });
1300  assert(segment_capacity_validation());
1301 }
1302 
1325 template <typename T, typename Segment, typename Policy>
1326 template <typename InputIt,
1327  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1328  InputIt>::type *>
1329 void
1331 {
1332  size_type count = static_cast<size_type>(std::distance(first, last));
1333  if (count > max_size())
1334  throw std::length_error("Assignable range exceeds max size.");
1335 
1336  pool_base pb = get_pool();
1337  transaction::run(pb, [&] {
1338  if (count > capacity())
1339  internal_reserve(count);
1340  else if (count < size())
1341  shrink(count);
1342 
1343  difference_type num;
1344  size_type end = policy::get_segment(count - 1);
1345  for (size_type i = 0; i < end; ++i) {
1346  size_type size = policy::segment_size(i);
1347  num = static_cast<difference_type>(size);
1348  _data[i].assign(first, std::next(first, num));
1349  std::advance(first, num);
1350  }
1351  num = static_cast<difference_type>(std::distance(first, last));
1352  _data[end].assign(first, std::next(first, num));
1353 
1354  _segments_used = end + 1;
1355  });
1356  assert(segment_capacity_validation());
1357 }
1358 
1379 template <typename T, typename Segment, typename Policy>
1380 void
1381 segment_vector<T, Segment, Policy>::assign(std::initializer_list<T> ilist)
1382 {
1383  assign(ilist.begin(), ilist.end());
1384 }
1385 
1402 template <typename T, typename Segment, typename Policy>
1403 void
1405 {
1406  if (this != &other)
1407  assign(other.cbegin(), other.cend());
1408 }
1409 
1425 template <typename T, typename Segment, typename Policy>
1426 void
1428 {
1429  if (this == &other)
1430  return;
1431 
1432  pool_base pb = get_pool();
1433  transaction::run(pb, [&] {
1434  _data = std::move(other._data);
1435  _segments_used = other._segments_used;
1436  other._segments_used = 0;
1437  });
1438 }
1439 
1456 template <typename T, typename Segment, typename Policy>
1457 void
1459 {
1460  assign(other.cbegin(), other.cend());
1461 }
1462 
1474 template <typename T, typename Segment, typename Policy>
1476 {
1477  free_data();
1478 }
1479 
1493 template <typename T, typename Segment, typename Policy>
1494 typename segment_vector<T, Segment, Policy>::reference
1496 {
1497  if (n >= size())
1498  throw std::out_of_range("segment_vector::at");
1499 
1500  detail::conditional_add_to_tx(&get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1501 
1502  return get(n);
1503 }
1504 
1515 template <typename T, typename Segment, typename Policy>
1516 typename segment_vector<T, Segment, Policy>::const_reference
1518 {
1519  if (n >= size())
1520  throw std::out_of_range("segment_vector::at");
1521  return get(n);
1522 }
1523 
1536 template <typename T, typename Segment, typename Policy>
1537 typename segment_vector<T, Segment, Policy>::const_reference
1539 {
1540  if (n >= size())
1541  throw std::out_of_range("segment_vector::const_at");
1542  return get(n);
1543 }
1544 
1556 template <typename T, typename Segment, typename Policy>
1557 typename segment_vector<T, Segment, Policy>::reference
1559 {
1560  reference element = get(n);
1561 
1562  detail::conditional_add_to_tx(&element, 1,
1563  POBJ_XADD_ASSUME_INITIALIZED);
1564 
1565  return element;
1566 }
1567 
1575 template <typename T, typename Segment, typename Policy>
1576 typename segment_vector<T, Segment, Policy>::const_reference
1578 {
1579  return get(n);
1580 }
1581 
1590 template <typename T, typename Segment, typename Policy>
1591 typename segment_vector<T, Segment, Policy>::reference
1593 {
1594  detail::conditional_add_to_tx(&_data[0][0], 1,
1595  POBJ_XADD_ASSUME_INITIALIZED);
1596 
1597  return _data[0][0];
1598 }
1599 
1605 template <typename T, typename Segment, typename Policy>
1606 typename segment_vector<T, Segment, Policy>::const_reference
1608 {
1609  return _data[0][0];
1610 }
1611 
1619 template <typename T, typename Segment, typename Policy>
1620 typename segment_vector<T, Segment, Policy>::const_reference
1622 {
1623  return _data[0][0];
1624 }
1625 
1634 template <typename T, typename Segment, typename Policy>
1635 typename segment_vector<T, Segment, Policy>::reference
1637 {
1638  reference element = get(size() - 1);
1639 
1640  detail::conditional_add_to_tx(&element, 1,
1641  POBJ_XADD_ASSUME_INITIALIZED);
1642 
1643  return element;
1644 }
1645 
1651 template <typename T, typename Segment, typename Policy>
1652 typename segment_vector<T, Segment, Policy>::const_reference
1654 {
1655  return get(size() - 1);
1656 }
1657 
1665 template <typename T, typename Segment, typename Policy>
1666 typename segment_vector<T, Segment, Policy>::const_reference
1668 {
1669  return get(size() - 1);
1670 }
1671 
1677 template <typename T, typename Segment, typename Policy>
1680 {
1681  return iterator(this, 0);
1682 }
1683 
1690 template <typename T, typename Segment, typename Policy>
1693 {
1694  return const_iterator(this, 0);
1695 }
1696 
1705 template <typename T, typename Segment, typename Policy>
1708 {
1709  return const_iterator(this, 0);
1710 }
1711 
1718 template <typename T, typename Segment, typename Policy>
1721 {
1722  return iterator(this, size());
1723 }
1724 
1731 template <typename T, typename Segment, typename Policy>
1734 {
1735  return const_iterator(this, size());
1736 }
1737 
1746 template <typename T, typename Segment, typename Policy>
1749 {
1750  return const_iterator(this, size());
1751 }
1752 
1759 template <typename T, typename Segment, typename Policy>
1760 typename segment_vector<T, Segment, Policy>::reverse_iterator
1762 {
1763  return reverse_iterator(end());
1764 }
1765 
1772 template <typename T, typename Segment, typename Policy>
1773 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1775 {
1776  return const_reverse_iterator(end());
1777 }
1778 
1787 template <typename T, typename Segment, typename Policy>
1788 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1790 {
1791  return rbegin();
1792 }
1793 
1800 template <typename T, typename Segment, typename Policy>
1801 typename segment_vector<T, Segment, Policy>::reverse_iterator
1803 {
1804  return reverse_iterator(begin());
1805 }
1806 
1813 template <typename T, typename Segment, typename Policy>
1814 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1816 {
1817  return const_reverse_iterator(begin());
1818 }
1819 
1828 template <typename T, typename Segment, typename Policy>
1829 typename segment_vector<T, Segment, Policy>::const_reverse_iterator
1831 {
1832  return rend();
1833 }
1834 
1848 template <typename T, typename Segment, typename Policy>
1850 segment_vector<T, Segment, Policy>::range(size_type start, size_type n)
1851 {
1852  if (start + n > size())
1853  throw std::out_of_range("segment_vector::range");
1854 
1855  snapshot_data(start, start + n);
1856 
1857  return {iterator(this, start), iterator(this, start + n)};
1858 }
1859 
1871 template <typename T, typename Segment, typename Policy>
1873 segment_vector<T, Segment, Policy>::range(size_type start, size_type n) const
1874 {
1875  if (start + n > size())
1876  throw std::out_of_range("segment_vector::range");
1877 
1878  return {const_iterator(this, start), const_iterator(this, start + n)};
1879 }
1880 
1892 template <typename T, typename Segment, typename Policy>
1894 segment_vector<T, Segment, Policy>::crange(size_type start, size_type n) const
1895 {
1896  if (start + n > size())
1897  throw std::out_of_range("segment_vector::range");
1898 
1899  return {const_iterator(this, start), const_iterator(this, start + n)};
1900 }
1901 
1907 template <typename T, typename Segment, typename Policy>
1908 constexpr bool
1910 {
1911  return size() == 0;
1912 }
1913 
1917 template <typename T, typename Segment, typename Policy>
1918 typename segment_vector<T, Segment, Policy>::size_type
1920 {
1921  size_type result = 0;
1922  for (size_type i = 0; i < _segments_used; ++i)
1923  result += _data.const_at(i).size();
1924  return result;
1925 }
1926 
1931 template <typename T, typename Segment, typename Policy>
1932 constexpr typename segment_vector<T, Segment, Policy>::size_type
1934 {
1935  return policy::max_size(_data);
1936 }
1937 
1954 template <typename T, typename Segment, typename Policy>
1955 void
1957 {
1958  if (capacity_new <= capacity())
1959  return;
1960 
1961  pool_base pb = get_pool();
1962  transaction::run(pb, [&] { internal_reserve(capacity_new); });
1963 }
1964 
1969 template <typename T, typename Segment, typename Policy>
1970 typename segment_vector<T, Segment, Policy>::size_type
1972 {
1973  if (_segments_used == 0)
1974  return 0;
1975  return policy::capacity(_segments_used - 1);
1976 }
1977 
1989 template <typename T, typename Segment, typename Policy>
1990 void
1992 {
1993  size_type new_last = policy::get_segment(size() - 1);
1994  if (_segments_used - 1 == new_last)
1995  return;
1996 
1997  pool_base pb = get_pool();
1998  transaction::run(pb, [&] {
1999  for (size_type i = new_last + 1; i < _segments_used; ++i)
2000  _data[i].free_data();
2001  _segments_used = new_last + 1;
2002  storage::resize(_data, _segments_used);
2003  });
2004 }
2005 
2017 template <typename T, typename Segment, typename Policy>
2018 void
2020 {
2021  pool_base pb = get_pool();
2022  transaction::run(pb, [&] { shrink(0); });
2023  assert(segment_capacity_validation());
2024 }
2025 
2038 template <typename T, typename Segment, typename Policy>
2039 void
2041 {
2042  pool_base pb = get_pool();
2043  transaction::run(pb, [&] {
2044  for (size_type i = 0; i < _segments_used; ++i)
2045  _data[i].free_data();
2046  _segments_used = 0;
2047  });
2048 }
2049 
2073 template <typename T, typename Segment, typename Policy>
2076 {
2077  return insert(pos, 1, value);
2078 }
2079 
2103 template <typename T, typename Segment, typename Policy>
2106 {
2107  size_type idx = static_cast<size_type>(pos - cbegin());
2108 
2109  pool_base pb = get_pool();
2110  transaction::run(pb, [&] {
2111  insert_gap(idx, 1);
2112  get(idx) = std::move(value);
2113  });
2114 
2115  return iterator(this, idx);
2116 }
2117 
2144 template <typename T, typename Segment, typename Policy>
2147  const T &value)
2148 {
2149  size_type idx = static_cast<size_type>(pos - cbegin());
2150 
2151  pool_base pb = get_pool();
2152  transaction::run(pb, [&] {
2153  insert_gap(idx, count);
2154  for (size_type i = idx; i < idx + count; ++i)
2155  get(i) = std::move(value);
2156  });
2157 
2158  return iterator(this, idx);
2159 }
2160 
2194 template <typename T, typename Segment, typename Policy>
2195 template <typename InputIt,
2196  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2197  InputIt>::type *>
2200  InputIt last)
2201 {
2202  size_type idx = static_cast<size_type>(pos - cbegin());
2203  size_type gap_size = static_cast<size_type>(std::distance(first, last));
2204 
2205  pool_base pb = get_pool();
2206  transaction::run(pb, [&] {
2207  insert_gap(idx, gap_size);
2208  for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2209  get(i) = *first;
2210  });
2211 
2212  return iterator(this, idx);
2213 }
2214 
2241 template <typename T, typename Segment, typename Policy>
2244  std::initializer_list<T> ilist)
2245 {
2246  return insert(pos, ilist.begin(), ilist.end());
2247 }
2248 
2277 template <typename T, typename Segment, typename Policy>
2278 template <class... Args>
2281 {
2282  size_type idx = static_cast<size_type>(pos - cbegin());
2283 
2284  pool_base pb = get_pool();
2285  transaction::run(pb, [&] {
2286  detail::temp_value<value_type,
2287  noexcept(T(std::forward<Args>(args)...))>
2288  tmp(std::forward<Args>(args)...);
2289  insert_gap(idx, 1);
2290  get(idx) = std::move(tmp.get());
2291  });
2292 
2293  return iterator(this, idx);
2294 }
2295 
2320 template <typename T, typename Segment, typename Policy>
2321 template <class... Args>
2322 typename segment_vector<T, Segment, Policy>::reference
2324 {
2325  assert(size() < max_size());
2326 
2327  pool_base pb = get_pool();
2328  transaction::run(pb, [&] {
2329  if (size() == capacity())
2330  internal_reserve(capacity() + 1);
2331 
2332  size_type segment = policy::get_segment(size());
2333  _data[segment].emplace_back(std::forward<Args>(args)...);
2334  });
2335 
2336  return back();
2337 }
2338 
2360 template <typename T, typename Segment, typename Policy>
2363 {
2364  return erase(pos, pos + 1);
2365 }
2366 
2391 template <typename T, typename Segment, typename Policy>
2394  const_iterator last)
2395 {
2396  size_type count = static_cast<size_type>(std::distance(first, last));
2397  size_type idx = static_cast<size_type>(first - cbegin());
2398 
2399  if (count == 0)
2400  return iterator(this, idx);
2401 
2402  pool_base pb = get_pool();
2403  transaction::run(pb, [&] {
2404  size_type _size = size();
2405 
2406  snapshot_data(idx, _size);
2407 
2408  /* Moving after-range elements to the place of deleted
2409  */
2410  iterator dest = iterator(this, idx);
2411  iterator begin = iterator(this, idx + count);
2412  iterator end = iterator(this, _size);
2413  std::move(begin, end, dest);
2414 
2415  /* Clearing the range where the elements were moved from
2416  */
2417  size_type middle = policy::get_segment(_size - count);
2418  size_type last = policy::get_segment(_size - 1);
2419  size_type middle_size = policy::index_in_segment(_size - count);
2420  for (size_type s = last; s > middle; --s)
2421  _data[s].clear();
2422  _data[middle].resize(middle_size);
2423 
2424  _segments_used = middle + 1;
2425  });
2426 
2427  assert(segment_capacity_validation());
2428 
2429  return iterator(this, idx);
2430 }
2431 
2450 template <typename T, typename Segment, typename Policy>
2451 void
2453 {
2454  emplace_back(value);
2455 }
2456 
2475 template <typename T, typename Segment, typename Policy>
2476 void
2478 {
2479  emplace_back(std::move(value));
2480 }
2481 
2495 template <typename T, typename Segment, typename Policy>
2496 void
2498 {
2499  if (empty())
2500  return;
2501 
2502  pool_base pb = get_pool();
2503  transaction::run(pb, [&] { shrink(size() - 1); });
2504  assert(segment_capacity_validation());
2505 }
2506 
2530 template <typename T, typename Segment, typename Policy>
2531 void
2533 {
2534  pool_base pb = get_pool();
2535  transaction::run(pb, [&] {
2536  size_type _size = size();
2537  if (count < _size)
2538  shrink(count);
2539  else {
2540  if (capacity() < count)
2541  internal_reserve(count);
2542  construct(_size, count - _size);
2543  }
2544  });
2545  assert(segment_capacity_validation());
2546 }
2547 
2572 template <typename T, typename Segment, typename Policy>
2573 void
2575  const value_type &value)
2576 {
2577  pool_base pb = get_pool();
2578  transaction::run(pb, [&] {
2579  size_type _size = size();
2580  if (count < _size)
2581  shrink(count);
2582  else {
2583  if (capacity() < count)
2584  internal_reserve(count);
2585  construct(_size, count - _size, value);
2586  }
2587  });
2588  assert(segment_capacity_validation());
2589 }
2590 
2594 template <typename T, typename Segment, typename Policy>
2595 void
2597 {
2598  pool_base pb = get_pool();
2599  transaction::run(pb, [&] {
2600  _data.swap(other._data);
2601  std::swap(_segments_used, other._segments_used);
2602  });
2603 }
2604 
2621 template <typename T, typename Segment, typename Policy>
2622 void
2624 {
2625  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2626 
2627  if (new_capacity > max_size())
2628  throw std::length_error("New capacity exceeds max size.");
2629 
2630  if (new_capacity == 0)
2631  return;
2632 
2633  size_type old_idx = policy::get_segment(capacity());
2634  size_type new_idx = policy::get_segment(new_capacity - 1);
2635  storage::resize(_data, new_idx + 1);
2636  for (size_type i = old_idx; i <= new_idx; ++i) {
2637  size_type segment_capacity = policy::segment_size(i);
2638  _data[i].reserve(segment_capacity);
2639  }
2640  _segments_used = new_idx + 1;
2641 
2642  assert(segment_capacity_validation());
2643 }
2644 
2671 template <typename T, typename Segment, typename Policy>
2672 template <typename... Args>
2673 void
2674 segment_vector<T, Segment, Policy>::construct(size_type idx, size_type count,
2675  Args &&... args)
2676 {
2677  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2678  assert(_segments_used - 1 >= policy::get_segment(size() + count - 1));
2679 
2680  for (size_type i = idx; i < idx + count; ++i) {
2681  size_type segment = policy::get_segment(i);
2682  _data[segment].emplace_back(std::forward<Args>(args)...);
2683  }
2684 }
2685 
2716 template <typename T, typename Segment, typename Policy>
2717 template <typename InputIt,
2718  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2719  InputIt>::type *>
2720 void
2722  InputIt first, InputIt last)
2723 {
2724  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2725  size_type count = static_cast<size_type>(std::distance(first, last));
2726  assert(count >= 0);
2727  assert(_segments_used - 1 >= policy::get_segment(size() + count - 1));
2728 
2729  for (size_type i = idx; i < idx + count; ++i, ++first) {
2730  size_type segment = policy::get_segment(i);
2731  _data[segment].emplace_back(*first);
2732  }
2733 }
2734 
2756 template <typename T, typename Segment, typename Policy>
2757 void
2758 segment_vector<T, Segment, Policy>::insert_gap(size_type idx, size_type count)
2759 {
2760  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2761 
2762  size_type _size = size();
2763 
2764  if (capacity() < _size + count)
2765  internal_reserve(_size + count);
2766 
2767  iterator dest = iterator(this, _size + count);
2768  iterator begin = iterator(this, idx);
2769  iterator end = iterator(this, _size);
2770 
2771  snapshot_data(idx, _size);
2772 
2773  resize(_size + count);
2774  std::move_backward(begin, end, dest);
2775 
2776  assert(segment_capacity_validation());
2777 }
2778 
2798 template <typename T, typename Segment, typename Policy>
2799 void
2801 {
2802  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2803  assert(size_new <= size());
2804 
2805  snapshot_data(size_new, size());
2806 
2807  size_type begin = policy::get_segment(size() - 1);
2808  size_type end = policy::get_segment(size_new);
2809  for (; begin > end; --begin) {
2810  _data[begin].clear();
2811  }
2812  size_type residue = policy::index_in_segment(size_new);
2813  _data[end].erase(_data[end].cbegin() + residue, _data[end].cend());
2814 }
2815 
2823 template <typename T, typename Segment, typename Policy>
2824 pool_base
2826 {
2827  auto pop = pmemobj_pool_by_ptr(this);
2828  assert(pop != nullptr);
2829  return pool_base(pop);
2830 }
2831 
2841 template <typename T, typename Segment, typename Policy>
2842 void
2844  size_type last)
2845 {
2846  if (first == last)
2847  return;
2848 
2849  size_type segment = policy::get_segment(first);
2850  size_type end = policy::get_segment(last - 1);
2851  size_type count = policy::segment_top(segment + 1) - first;
2852 
2853  while (segment != end) {
2854  detail::conditional_add_to_tx(&cget(first), count,
2855  POBJ_XADD_ASSUME_INITIALIZED);
2856  first = policy::segment_top(++segment);
2857  count = policy::segment_size(segment);
2858  }
2859  detail::conditional_add_to_tx(&cget(first), last - first,
2860  POBJ_XADD_ASSUME_INITIALIZED);
2861 }
2862 
2868 template <typename T, typename Segment, typename Policy>
2869 typename segment_vector<T, Segment, Policy>::reference
2871 {
2872  size_type s_idx = policy::get_segment(n);
2873  size_type local_idx = policy::index_in_segment(n);
2874 
2875  return _data[s_idx][local_idx];
2876 }
2877 
2883 template <typename T, typename Segment, typename Policy>
2884 typename segment_vector<T, Segment, Policy>::const_reference
2886 {
2887  size_type s_idx = policy::get_segment(n);
2888  size_type local_idx = policy::index_in_segment(n);
2889 
2890  return _data[s_idx][local_idx];
2891 }
2892 
2898 template <typename T, typename Segment, typename Policy>
2899 typename segment_vector<T, Segment, Policy>::const_reference
2901 {
2902  size_type s_idx = policy::get_segment(n);
2903  size_type local_idx = policy::index_in_segment(n);
2904 
2905  return _data[s_idx][local_idx];
2906 }
2907 
2915 template <typename T, typename Segment, typename Policy>
2916 bool
2918 {
2919  for (size_type i = 0; i < _segments_used; ++i)
2920  if (_data.const_at(i).capacity() != policy::segment_size(i))
2921  return false;
2922  return true;
2923 }
2924 
2931 template <typename T, typename Segment, typename Policy>
2932 void
2935 {
2936  lhs.swap(rhs);
2937 }
2938 
2953 template <typename T, typename Segment, typename Policy>
2954 bool
2957 {
2958  return lhs.size() == rhs.size() &&
2959  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2960 }
2961 
2977 template <typename T, typename Segment, typename Policy>
2978 bool
2981 {
2982  return !(lhs == rhs);
2983 }
2984 
2997 template <typename T, typename Segment, typename Policy>
2998 bool
3001 {
3002  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
3003  rhs.end());
3004 }
3005 
3018 template <typename T, typename Segment, typename Policy>
3019 bool
3022 {
3023  return !(rhs < lhs);
3024 }
3025 
3038 template <typename T, typename Segment, typename Policy>
3039 bool
3042 {
3043  return rhs < lhs;
3044 }
3045 
3058 template <typename T, typename Segment, typename Policy>
3059 bool
3062 {
3063  return !(lhs < rhs);
3064 }
3065 
3079 template <typename T, typename Segment, typename Policy>
3080 bool
3082  const std::vector<T> &rhs)
3083 {
3084  return lhs.size() == rhs.size() &&
3085  std::equal(lhs.begin(), lhs.end(), rhs.begin());
3086 }
3087 
3101 template <typename T, typename Segment, typename Policy>
3102 bool
3104  const std::vector<T> &rhs)
3105 {
3106  return !(lhs == rhs);
3107 }
3108 
3120 template <typename T, typename Segment, typename Policy>
3121 bool
3123  const std::vector<T> &rhs)
3124 {
3125  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
3126  rhs.end());
3127 }
3128 
3140 template <typename T, typename Segment, typename Policy>
3141 bool
3143  const std::vector<T> &rhs)
3144 {
3145  return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
3146  lhs.begin(), lhs.end()));
3147 }
3148 
3161 template <typename T, typename Segment, typename Policy>
3162 bool
3164  const std::vector<T> &rhs)
3165 {
3166  return !(lhs <= rhs);
3167 }
3168 
3180 template <typename T, typename Segment, typename Policy>
3181 bool
3183  const std::vector<T> &rhs)
3184 {
3185  return !(lhs < rhs);
3186 }
3187 
3201 template <typename T, typename Segment, typename Policy>
3202 bool
3203 operator==(const std::vector<T> &lhs,
3205 {
3206  return rhs == lhs;
3207 }
3208 
3222 template <typename T, typename Segment, typename Policy>
3223 bool
3224 operator!=(const std::vector<T> &lhs,
3226 {
3227  return !(lhs == rhs);
3228 }
3229 
3241 template <typename T, typename Segment, typename Policy>
3242 bool
3243 operator<(const std::vector<T> &lhs,
3245 {
3246  return rhs > lhs;
3247 }
3248 
3260 template <typename T, typename Segment, typename Policy>
3261 bool
3262 operator<=(const std::vector<T> &lhs,
3264 {
3265  return !(rhs < lhs);
3266 }
3267 
3280 template <typename T, typename Segment, typename Policy>
3281 bool
3282 operator>(const std::vector<T> &lhs,
3284 {
3285  return rhs < lhs;
3286 }
3287 
3299 template <typename T, typename Segment, typename Policy>
3300 bool
3301 operator>=(const std::vector<T> &lhs,
3303 {
3304  return !(lhs < rhs);
3305 }
3306 
3307 } /* namespace experimental */
3308 } /* namespace obj */
3309 } /* namespace pmem */
3310 
3311 #endif /* LIBPMEMOBJ_SEGMENT_VECTOR_HPP */
void construct_range(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: segment_vector.hpp:2721
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:402
iterator insert(const_iterator pos, const T &value)
Inserts value before pos in the container transactionally.
Definition: segment_vector.hpp:2075
size_type capacity() const noexcept
Definition: segment_vector.hpp:1971
reference get(size_type n)
Private helper function.
Definition: segment_vector.hpp:2870
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:913
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:336
reference front()
Access the first element and add this element to a transaction.
Definition: segment_vector.hpp:1592
pool_base get_pool() const noexcept
Private helper function.
Definition: segment_vector.hpp:2825
const_reference cback() const
Access the last element.
Definition: segment_vector.hpp:1667
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
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: segment_vector.hpp:1748
segment_iterator & operator--()
Prefix decrement.
Definition: segment_vector.hpp:252
The non-template pool base class.
Definition: pool.hpp:67
temp_value template class for caching objects.
~segment_vector()
Destructor.
Definition: segment_vector.hpp:1475
Segment table is a data type with a vector-like interface The difference is that it does not do reall...
Definition: segment_vector.hpp:711
iterator begin()
Returns an iterator to the beginning.
Definition: segment_vector.hpp:1679
void free_data()
Clears the content of a segment_vector and frees all allocated persistent memory for data transaction...
Definition: segment_vector.hpp:2040
void pop_back()
Removes the last element of the container transactionally.
Definition: segment_vector.hpp:2497
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: segment_vector.hpp:1909
T & get(pmem::obj::array< T, N > &a)
Non-member get function.
Definition: array.hpp:923
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:56
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:752
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:672
void shrink_to_fit()
Requests transactional removal of unused capacity.
Definition: segment_vector.hpp:1991
segment_iterator & operator-=(difference_type idx)
Random access decrementing with assignment.
Definition: segment_vector.hpp:291
C++ pmemobj transactions.
Convenience extensions for the resides on pmem property template.
const_reference cfront() const
Access the first element.
Definition: segment_vector.hpp:1621
reference operator *() const
Indirection (dereference).
Definition: segment_vector.hpp:454
void construct(size_type idx, size_type count, Args &&... args)
Private helper function.
Definition: segment_vector.hpp:2674
void push_back(const T &value)
Appends the given element value to the end of the container transactionally.
Definition: segment_vector.hpp:2452
bool operator<(const segment_iterator< Container, C > &rhs) const
Less operator.
Definition: segment_vector.hpp:372
Functions for destroying arrays.
Commonly used functionality.
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:783
iterator end()
Returns an iterator to past the end.
Definition: segment_vector.hpp:1720
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:2800
segment_iterator & operator+=(difference_type idx)
Random access incrementing with assignment.
Definition: segment_vector.hpp:239
void reserve(size_type capacity_new)
Increases the capacity of the segment_vector to capacity_new transactionally.
Definition: segment_vector.hpp:1956
iterator emplace(const_iterator pos, Args &&... args)
Inserts a new element into the container directly before pos.
Definition: segment_vector.hpp:2280
void swap(segment_vector &other)
Exchanges the contents of the container with other transactionally.
Definition: segment_vector.hpp:2596
bool operator!=(const segment_iterator< Container, C > &rhs) const
Not equal operator.
Definition: segment_vector.hpp:353
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1789
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: segment_vector.hpp:1538
slice< iterator > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: segment_vector.hpp:1850
void assign(size_type count, const_reference value)
Replaces the contents with count copies of value value transactionally.
Definition: segment_vector.hpp:1280
reference at(size_type n)
Access element at specific index with bounds checking and add it to a transaction.
Definition: segment_vector.hpp:1495
bool operator>(const segment_iterator< Container, C > &rhs) const
Greater operator.
Definition: segment_vector.hpp:395
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:2323
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:1933
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:2900
segment_iterator & operator++()
Prefix increment.
Definition: segment_vector.hpp:200
Template class for caching objects based on constructor'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:1761
pmem::obj::vector - persistent container with std::vector compatible interface.
Definition: vector.hpp:69
bool operator<=(const segment_iterator< Container, C > &rhs) const
Less or equal operator.
Definition: segment_vector.hpp:418
void internal_reserve(size_type new_capacity)
Private helper method.
Definition: segment_vector.hpp:2623
segment_vector & operator=(const segment_vector &other)
Copy assignment operator.
Definition: segment_vector.hpp:1177
bool segment_capacity_validation() const
Private helper function.
Definition: segment_vector.hpp:2917
segment_iterator operator-(difference_type idx) const
Random access decrementing.
Definition: segment_vector.hpp:279
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:763
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:1707
size_type size() const noexcept
Definition: segment_vector.hpp:1919
iterator erase(const_iterator pos)
Removes the element at pos.
Definition: segment_vector.hpp:2362
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: segment_vector.hpp:1830
segment_vector()
Default constructor.
Definition: segment_vector.hpp:949
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:227
void insert_gap(size_type idx, size_type count)
Private helper function.
Definition: segment_vector.hpp:2758
reference back()
Access the last element and add this element to a transaction.
Definition: segment_vector.hpp:1636
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: segment_vector.hpp:1802
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:518
pointer operator->() const
Member access.
Definition: segment_vector.hpp:464
void clear()
Clears the content of a segment_vector transactionally.
Definition: segment_vector.hpp:2019
A persistent version of concurrent hash map implementation Ref: https://arxiv.org/abs/1509....
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:1558
bool operator>=(const segment_iterator< Container, C > &rhs) const
Greater or equal operator.
Definition: segment_vector.hpp:441
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:157
void snapshot_data(size_type idx_first, size_type idx_last)
Private helper function.
Definition: segment_vector.hpp:2843
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:803
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: segment_vector.hpp:1894
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:773
void resize(size_type count)
Resizes the container to count elements transactionally.
Definition: segment_vector.hpp:2532
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