PMDK C++ bindings  1.13.0-git23.gf49772ac
This is the C++ bindings documentation for PMDK's libpmemobj.
vector.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2018-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_VECTOR_HPP
10 #define LIBPMEMOBJ_CPP_VECTOR_HPP
11 
16 #include <libpmemobj++/detail/temp_value.hpp>
19 #include <libpmemobj++/pext.hpp>
20 #include <libpmemobj++/slice.hpp>
22 #include <libpmemobj++/utils.hpp>
23 #include <libpmemobj/base.h>
24 
25 #include <algorithm>
26 #include <cassert>
27 #include <utility>
28 #include <vector>
29 
30 namespace pmem
31 {
32 
33 namespace obj
34 {
35 
40 template <typename T>
41 class vector {
42 public:
43  /* Member types */
44  using value_type = T;
45  using size_type = std::size_t;
46  using difference_type = std::ptrdiff_t;
47  using reference = value_type &;
48  using const_reference = const value_type &;
49  using pointer = value_type *;
50  using const_pointer = const value_type *;
52  using const_iterator = const_pointer;
53  using reverse_iterator = std::reverse_iterator<iterator>;
54  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
57  /* func argument type definition for 'for_each_ptr' method */
58  using for_each_ptr_function =
59  std::function<void(persistent_ptr_base &)>;
60 
61  /* Constructors */
62  vector();
63  vector(size_type count, const value_type &value);
64  explicit vector(size_type count);
65  template <typename InputIt,
66  typename std::enable_if<
68  InputIt>::type * = nullptr>
69  vector(InputIt first, InputIt last);
70  vector(const vector &other);
71  vector(vector &&other);
72  vector(std::initializer_list<T> init);
73  vector(const std::vector<T> &other);
74 
75  /* Assign operators */
76  vector &operator=(const vector &other);
77  vector &operator=(vector &&other);
78  vector &operator=(std::initializer_list<T> ilist);
79  vector &operator=(const std::vector<T> &other);
80 
81  /* Assign methods */
82  void assign(size_type count, const T &value);
83  template <typename InputIt,
84  typename std::enable_if<
86  InputIt>::type * = nullptr>
87  void assign(InputIt first, InputIt last);
88  void assign(std::initializer_list<T> ilist);
89  void assign(const vector &other);
90  void assign(vector &&other);
91  void assign(const std::vector<T> &other);
92 
93  /* Destructor */
95 
96  /* Element access */
97  reference at(size_type n);
98  const_reference at(size_type n) const;
99  const_reference const_at(size_type n) const;
100  reference operator[](size_type n);
101  const_reference operator[](size_type n) const;
102  reference front();
103  const_reference front() const;
104  const_reference cfront() const;
105  reference back();
106  const_reference back() const;
107  const_reference cback() const;
108  value_type *data();
109  const value_type *data() const noexcept;
110  const value_type *cdata() const noexcept;
111 
112  /* Iterators */
114  const_iterator begin() const noexcept;
115  const_iterator cbegin() const noexcept;
117  const_iterator end() const noexcept;
118  const_iterator cend() const noexcept;
119  reverse_iterator rbegin();
120  const_reverse_iterator rbegin() const noexcept;
121  const_reverse_iterator crbegin() const noexcept;
122  reverse_iterator rend();
123  const_reverse_iterator rend() const noexcept;
124  const_reverse_iterator crend() const noexcept;
125 
126  /* Range */
127  slice<pointer> range(size_type start, size_type n);
128  slice<range_snapshotting_iterator> range(size_type start, size_type n,
129  size_type snapshot_size);
130  slice<const_iterator> range(size_type start, size_type n) const;
131  slice<const_iterator> crange(size_type start, size_type n) const;
132  void for_each_ptr(for_each_ptr_function func);
133 
134  /* Capacity */
135  constexpr bool empty() const noexcept;
136  size_type size() const noexcept;
137  constexpr size_type max_size() const noexcept;
138  void reserve(size_type capacity_new);
139  size_type capacity() const noexcept;
141 
142  /* Modifiers */
143  void clear();
144  void free_data();
145  iterator insert(const_iterator pos, const T &value);
146  iterator insert(const_iterator pos, T &&value);
147  iterator insert(const_iterator pos, size_type count, const T &value);
148  template <typename InputIt,
149  typename std::enable_if<
150  detail::is_input_iterator<InputIt>::value,
151  InputIt>::type * = nullptr>
152  iterator insert(const_iterator pos, InputIt first, InputIt last);
153  iterator insert(const_iterator pos, std::initializer_list<T> ilist);
154  template <class... Args>
155  iterator emplace(const_iterator pos, Args &&... args);
156  template <class... Args>
157  reference emplace_back(Args &&... args);
158  iterator erase(const_iterator pos);
159  iterator erase(const_iterator first, const_iterator last);
160  void push_back(const T &value);
161  void push_back(T &&value);
162  void pop_back();
163  void resize(size_type count);
164  void resize(size_type count, const value_type &value);
165  void swap(vector &other);
166 
167 private:
168  /* helper iterator */
169  template <typename P>
170  struct single_element_iterator {
171  using iterator_category = std::input_iterator_tag;
172  using value_type = P;
173  using difference_type = std::ptrdiff_t;
174  using pointer = const P *;
175  using reference = const P &;
176 
177  const P *ptr;
178  std::size_t count;
179 
180  single_element_iterator(const P *ptr, std::size_t count = 0)
181  : ptr(ptr), count(count)
182  {
183  }
184 
185  reference operator*()
186  {
187  return *ptr;
188  }
189 
190  pointer operator->()
191  {
192  return ptr;
193  }
194 
195  single_element_iterator &
196  operator++()
197  {
198  count++;
199  return *this;
200  }
201 
202  single_element_iterator
203  operator++(int)
204  {
205  single_element_iterator tmp =
206  single_element_iterator(ptr, count);
207  count++;
208  return tmp;
209  }
210 
211  difference_type
212  operator-(const single_element_iterator &rhs)
213  {
214  return count - rhs.count;
215  }
216 
217  bool
218  operator!=(const single_element_iterator &rhs)
219  {
220  return ptr != rhs.ptr || count != rhs.count;
221  }
222  };
223 
224  /* helper functions */
225  void alloc(size_type size);
226  void check_pmem();
228  template <typename... Args>
229  void construct_at_end(size_type count, Args &&... args);
230  template <typename InputIt,
231  typename std::enable_if<
233  InputIt>::type * = nullptr>
234  void construct_at_end(InputIt first, InputIt last);
235  void dealloc();
237  template <typename InputIt>
238  void internal_insert(size_type idx, InputIt first, InputIt last);
239  void realloc(size_type size);
240  size_type get_recommended_capacity(size_type at_least) const;
241  void shrink(size_type size_new);
242  void add_data_to_tx(size_type idx_first, size_type num);
243  template <typename InputIt>
244  void construct_or_assign(size_type idx, InputIt first, InputIt last);
245  void move_elements_backward(pointer first, pointer last,
246  pointer d_last);
247 
248  p<size_type> _size;
249  p<size_type> _capacity;
250 
251  /* Underlying array */
252  persistent_ptr<T[]> _data;
253 };
254 
255 /* Non-member swap */
256 template <typename T>
257 void swap(vector<T> &lhs, vector<T> &rhs);
258 
259 /*
260  * Comparison operators between pmem::obj::vector<T> and
261  * pmem::obj::vector<T>
262  */
263 template <typename T>
264 bool operator==(const vector<T> &lhs, const vector<T> &rhs);
265 template <typename T>
266 bool operator!=(const vector<T> &lhs, const vector<T> &rhs);
267 template <typename T>
268 bool operator<(const vector<T> &lhs, const vector<T> &rhs);
269 template <typename T>
270 bool operator<=(const vector<T> &lhs, const vector<T> &rhs);
271 template <typename T>
272 bool operator>(const vector<T> &lhs, const vector<T> &rhs);
273 template <typename T>
274 bool operator>=(const vector<T> &lhs, const vector<T> &rhs);
275 
276 /*
277  * Comparison operators between pmem::obj::vector<T> and
278  * std::vector<T>
279  */
280 template <typename T>
281 bool operator==(const vector<T> &lhs, const std::vector<T> &rhs);
282 template <typename T>
283 bool operator!=(const vector<T> &lhs, const std::vector<T> &rhs);
284 template <typename T>
285 bool operator<(const vector<T> &lhs, const std::vector<T> &rhs);
286 template <typename T>
287 bool operator<=(const vector<T> &lhs, const std::vector<T> &rhs);
288 template <typename T>
289 bool operator>(const vector<T> &lhs, const std::vector<T> &rhs);
290 template <typename T>
291 bool operator>=(const vector<T> &lhs, const std::vector<T> &rhs);
292 
293 /*
294  * Comparison operators between std::vector<T> and
295  * pmem::obj::vector<T>
296  */
297 template <typename T>
298 bool operator==(const std::vector<T> &lhs, const vector<T> &rhs);
299 template <typename T>
300 bool operator!=(const std::vector<T> &lhs, const vector<T> &rhs);
301 template <typename T>
302 bool operator<(const std::vector<T> &lhs, const vector<T> &rhs);
303 template <typename T>
304 bool operator<=(const std::vector<T> &lhs, const vector<T> &rhs);
305 template <typename T>
306 bool operator>(const std::vector<T> &lhs, const vector<T> &rhs);
307 template <typename T>
308 bool operator>=(const std::vector<T> &lhs, const vector<T> &rhs);
309 
319 template <typename T>
321 {
322  check_pmem();
323  check_tx_stage_work();
324 
325  _data = nullptr;
326  _size = 0;
327  _capacity = 0;
328 }
329 
348 template <typename T>
349 vector<T>::vector(size_type count, const value_type &value)
350 {
351  check_pmem();
352  check_tx_stage_work();
353 
354  _data = nullptr;
355  _size = 0;
356  alloc(count);
357  construct_at_end(count, value);
358 }
359 
377 template <typename T>
378 vector<T>::vector(size_type count)
379 {
380  check_pmem();
381  check_tx_stage_work();
382 
383  _data = nullptr;
384  _size = 0;
385  alloc(count);
386  construct_at_end(count);
387 }
388 
411 template <typename T>
412 template <typename InputIt,
413  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
414  InputIt>::type *>
415 vector<T>::vector(InputIt first, InputIt last)
416 {
417  check_pmem();
418  check_tx_stage_work();
419 
420  _data = nullptr;
421  _size = 0;
422  alloc(static_cast<size_type>(std::distance(first, last)));
423  construct_at_end(first, last);
424 }
425 
444 template <typename T>
446 {
447  check_pmem();
448  check_tx_stage_work();
449 
450  _data = nullptr;
451  _size = 0;
452  alloc(other.capacity());
453  construct_at_end(other.cbegin(), other.cend());
454 }
455 
475 template <typename T>
477 {
478  check_pmem();
479  check_tx_stage_work();
480 
481  _data = other._data;
482  _capacity = other.capacity();
483  _size = other.size();
484  other._data = nullptr;
485  other._capacity = other._size = 0;
486 }
487 
505 template <typename T>
506 vector<T>::vector(std::initializer_list<T> init)
507  : vector(init.begin(), init.end())
508 {
509 }
510 
529 template <typename T>
530 vector<T>::vector(const std::vector<T> &other)
531  : vector(other.cbegin(), other.cend())
532 {
533 }
534 
546 template <typename T>
547 vector<T> &
549 {
550  assign(other);
551 
552  return *this;
553 }
554 
565 template <typename T>
566 vector<T> &
568 {
569  assign(std::move(other));
570 
571  return *this;
572 }
573 
583 template <typename T>
584 vector<T> &
585 vector<T>::operator=(std::initializer_list<T> ilist)
586 {
587  assign(ilist.begin(), ilist.end());
588 
589  return *this;
590 }
591 
604 template <typename T>
605 vector<T> &
606 vector<T>::operator=(const std::vector<T> &other)
607 {
608  assign(other);
609 
610  return *this;
611 }
612 
629 template <typename T>
630 void
631 vector<T>::assign(size_type count, const_reference value)
632 {
633  pool_base pb = get_pool();
634 
635  flat_transaction::run(pb, [&] {
636  if (count <= capacity()) {
637  /*
638  * Reallocation is not needed. First, replace old
639  * elements with new ones in range [0, size()).
640  * Depending on count, either call remaining old
641  * elements destructors, or append more new elements.
642  */
643  size_type size_old = _size;
644  add_data_to_tx(0, size_old);
645 
646  std::fill_n(
647  _data.get(),
648  (std::min)(count,
649  static_cast<size_type>(size_old)),
650  value);
651 
652  if (count > size_old) {
653  add_data_to_tx(size_old, count - size_old);
654  construct_at_end(count - size_old, value);
655  } else {
656  shrink(count);
657  }
658  } else {
659  dealloc();
660  alloc(count);
661  construct_at_end(count, value);
662  }
663  });
664 }
665 
684 template <typename T>
685 template <typename InputIt,
686  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
687  InputIt>::type *>
688 void
689 vector<T>::assign(InputIt first, InputIt last)
690 {
691  pool_base pb = get_pool();
692 
693  size_type size_new = static_cast<size_type>(std::distance(first, last));
694 
695  flat_transaction::run(pb, [&] {
696  if (size_new <= capacity()) {
697  /*
698  * Reallocation is not needed. First, replace old
699  * elements with new ones in range [0, size()).
700  * Depending on size_new, either call remaining old
701  * elements destructors, or append more new elements.
702  */
703  size_type size_old = _size;
704  add_data_to_tx(0, size_old);
705 
706  InputIt mid = last;
707  bool growing = size_new > size_old;
708 
709  if (growing) {
710  add_data_to_tx(size_old, size_new - size_old);
711 
712  mid = first;
713  std::advance(mid, size_old);
714  }
715 
716  iterator shrink_to = std::copy(first, mid, &_data[0]);
717 
718  if (growing) {
719  construct_at_end(mid, last);
720  } else {
721  shrink(static_cast<size_type>(std::distance(
722  iterator(&_data[0]), shrink_to)));
723  }
724  } else {
725  dealloc();
726  alloc(size_new);
727  construct_at_end(first, last);
728  }
729  });
730 }
731 
747 template <typename T>
748 void
749 vector<T>::assign(std::initializer_list<T> ilist)
750 {
751  assign(ilist.begin(), ilist.end());
752 }
753 
765 template <typename T>
766 void
768 {
769  if (this != &other)
770  assign(other.cbegin(), other.cend());
771 }
772 
784 template <typename T>
785 void
787 {
788  if (this == &other)
789  return;
790 
791  pool_base pb = get_pool();
792 
793  flat_transaction::run(pb, [&] {
794  dealloc();
795 
796  _data = other._data;
797  _capacity = other._capacity;
798  _size = other._size;
799 
800  other._data = nullptr;
801  other._capacity = other._size = 0;
802  });
803 }
804 
817 template <typename T>
818 void
819 vector<T>::assign(const std::vector<T> &other)
820 {
821  assign(other.cbegin(), other.cend());
822 }
823 
831 template <typename T>
833 {
834  try {
835  free_data();
836  } catch (...) {
837  std::terminate();
838  }
839 }
840 
853 template <typename T>
854 typename vector<T>::reference
855 vector<T>::at(size_type n)
856 {
857  if (n >= _size)
858  throw std::out_of_range("vector::at");
859 
860  detail::conditional_add_to_tx(&_data[static_cast<difference_type>(n)],
861  1, POBJ_XADD_ASSUME_INITIALIZED);
862 
863  return _data[static_cast<difference_type>(n)];
864 }
865 
875 template <typename T>
876 typename vector<T>::const_reference
877 vector<T>::at(size_type n) const
878 {
879  if (n >= _size)
880  throw std::out_of_range("vector::at");
881 
882  return _data[static_cast<difference_type>(n)];
883 }
884 
897 template <typename T>
898 typename vector<T>::const_reference
899 vector<T>::const_at(size_type n) const
900 {
901  if (n >= _size)
902  throw std::out_of_range("vector::const_at");
903 
904  return _data[static_cast<difference_type>(n)];
905 }
906 
918 template <typename T>
919 typename vector<T>::reference vector<T>::operator[](size_type n)
920 {
921  detail::conditional_add_to_tx(&_data[static_cast<difference_type>(n)],
922  1, POBJ_XADD_ASSUME_INITIALIZED);
923 
924  return _data[static_cast<difference_type>(n)];
925 }
926 
934 template <typename T>
935 typename vector<T>::const_reference vector<T>::operator[](size_type n) const
936 {
937  return _data[static_cast<difference_type>(n)];
938 }
939 
948 template <typename T>
949 typename vector<T>::reference
951 {
952  detail::conditional_add_to_tx(&_data[0], 1,
953  POBJ_XADD_ASSUME_INITIALIZED);
954 
955  return _data[0];
956 }
957 
963 template <typename T>
964 typename vector<T>::const_reference
966 {
967  return _data[0];
968 }
969 
977 template <typename T>
978 typename vector<T>::const_reference
980 {
981  return _data[0];
982 }
983 
992 template <typename T>
993 typename vector<T>::reference
995 {
996  detail::conditional_add_to_tx(
997  &_data[static_cast<difference_type>(size() - 1)], 1,
998  POBJ_XADD_ASSUME_INITIALIZED);
999 
1000  return _data[static_cast<difference_type>(size() - 1)];
1001 }
1002 
1008 template <typename T>
1009 typename vector<T>::const_reference
1011 {
1012  return _data[static_cast<difference_type>(size() - 1)];
1013 }
1014 
1022 template <typename T>
1023 typename vector<T>::const_reference
1025 {
1026  return _data[static_cast<difference_type>(size() - 1)];
1027 }
1028 
1038 template <typename T>
1039 typename vector<T>::value_type *
1041 {
1042  add_data_to_tx(0, _size);
1043 
1044  return _data.get();
1045 }
1046 
1052 template <typename T>
1053 const typename vector<T>::value_type *
1054 vector<T>::data() const noexcept
1055 {
1056  return _data.get();
1057 }
1058 
1066 template <typename T>
1067 const typename vector<T>::value_type *
1068 vector<T>::cdata() const noexcept
1069 {
1070  return _data.get();
1071 }
1072 
1078 template <typename T>
1079 typename vector<T>::iterator
1081 {
1082  return iterator(_data.get());
1083 }
1084 
1090 template <typename T>
1091 typename vector<T>::const_iterator
1092 vector<T>::begin() const noexcept
1093 {
1094  return const_iterator(_data.get());
1095 }
1096 
1104 template <typename T>
1105 typename vector<T>::const_iterator
1106 vector<T>::cbegin() const noexcept
1107 {
1108  return const_iterator(_data.get());
1109 }
1110 
1116 template <typename T>
1117 typename vector<T>::iterator
1119 {
1120  return iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1121 }
1122 
1128 template <typename T>
1129 typename vector<T>::const_iterator
1130 vector<T>::end() const noexcept
1131 {
1132  return const_iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1133 }
1134 
1142 template <typename T>
1143 typename vector<T>::const_iterator
1144 vector<T>::cend() const noexcept
1145 {
1146  return const_iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1147 }
1148 
1154 template <typename T>
1155 typename vector<T>::reverse_iterator
1157 {
1158  return reverse_iterator(end());
1159 }
1160 
1166 template <typename T>
1167 typename vector<T>::const_reverse_iterator
1168 vector<T>::rbegin() const noexcept
1169 {
1170  return const_reverse_iterator(cend());
1171 }
1172 
1180 template <typename T>
1181 typename vector<T>::const_reverse_iterator
1182 vector<T>::crbegin() const noexcept
1183 {
1184  return const_reverse_iterator(cend());
1185 }
1186 
1193 template <typename T>
1194 typename vector<T>::reverse_iterator
1196 {
1197  return reverse_iterator(begin());
1198 }
1199 
1206 template <typename T>
1207 typename vector<T>::const_reverse_iterator
1208 vector<T>::rend() const noexcept
1209 {
1210  return const_reverse_iterator(cbegin());
1211 }
1212 
1221 template <typename T>
1222 typename vector<T>::const_reverse_iterator
1223 vector<T>::crend() const noexcept
1224 {
1225  return const_reverse_iterator(cbegin());
1226 }
1227 
1241 template <typename T>
1243 vector<T>::range(size_type start, size_type n)
1244 {
1245  if (start + n > size())
1246  throw std::out_of_range("vector::range");
1247 
1248  detail::conditional_add_to_tx(cdata() + start, n,
1249  POBJ_XADD_ASSUME_INITIALIZED);
1250 
1251  return {_data.get() + start, _data.get() + start + n};
1252 }
1253 
1269 template <typename T>
1271 vector<T>::range(size_type start, size_type n, size_type snapshot_size)
1272 {
1273  if (start + n > size())
1274  throw std::out_of_range("vector::range");
1275 
1276  if (snapshot_size > n)
1277  snapshot_size = n;
1278 
1279  return {range_snapshotting_iterator(_data.get() + start,
1280  _data.get() + start, n,
1281  snapshot_size),
1282  range_snapshotting_iterator(_data.get() + start + n,
1283  _data.get() + start, n,
1284  snapshot_size)};
1285 }
1286 
1298 template <typename T>
1300 vector<T>::range(size_type start, size_type n) const
1301 {
1302  if (start + n > size())
1303  throw std::out_of_range("vector::range");
1304 
1305  return {const_iterator(cdata() + start),
1306  const_iterator(cdata() + start + n)};
1307 }
1308 
1320 template <typename T>
1322 vector<T>::crange(size_type start, size_type n) const
1323 {
1324  if (start + n > size())
1325  throw std::out_of_range("vector::crange");
1326 
1327  return {const_iterator(cdata() + start),
1328  const_iterator(cdata() + start + n)};
1329 }
1330 
1336 template <typename T>
1337 constexpr bool
1338 vector<T>::empty() const noexcept
1339 {
1340  return _size == 0;
1341 }
1342 
1346 template <typename T>
1347 typename vector<T>::size_type
1348 vector<T>::size() const noexcept
1349 {
1350  return _size;
1351 }
1352 
1357 template <typename T>
1358 constexpr typename vector<T>::size_type
1359 vector<T>::max_size() const noexcept
1360 {
1361  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(value_type);
1362 }
1363 
1382 template <typename T>
1383 void
1384 vector<T>::reserve(size_type capacity_new)
1385 {
1386  if (capacity_new <= _capacity)
1387  return;
1388 
1389  pool_base pb = get_pool();
1390  flat_transaction::run(pb, [&] { realloc(capacity_new); });
1391 }
1392 
1396 template <typename T>
1397 typename vector<T>::size_type
1398 vector<T>::capacity() const noexcept
1399 {
1400  return _capacity;
1401 }
1402 
1417 template <typename T>
1418 void
1420 {
1421  size_type capacity_new = size();
1422  if (capacity() == capacity_new)
1423  return;
1424 
1425  pool_base pb = get_pool();
1426  flat_transaction::run(pb, [&] { realloc(capacity_new); });
1427 }
1428 
1437 template <typename T>
1438 void
1440 {
1441  pool_base pb = get_pool();
1442  flat_transaction::run(pb, [&] { shrink(0); });
1443 }
1444 
1457 template <typename T>
1458 void
1460 {
1461  if (_data == nullptr)
1462  return;
1463 
1464  pool_base pb = get_pool();
1465  flat_transaction::run(pb, [&] { dealloc(); });
1466 }
1467 
1492 template <typename T>
1493 typename vector<T>::iterator
1494 vector<T>::insert(const_iterator pos, const value_type &value)
1495 {
1496  return insert(pos, 1, value);
1497 }
1498 
1523 template <typename T>
1524 typename vector<T>::iterator
1525 vector<T>::insert(const_iterator pos, value_type &&value)
1526 {
1527  pool_base pb = get_pool();
1528 
1529  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1530 
1531  flat_transaction::run(pb, [&] {
1532  internal_insert(idx, std::make_move_iterator(&value),
1533  std::make_move_iterator(&value + 1));
1534  });
1535 
1536  return iterator(&_data[static_cast<difference_type>(idx)]);
1537 }
1538 
1567 template <typename T>
1568 typename vector<T>::iterator
1569 vector<T>::insert(const_iterator pos, size_type count, const value_type &value)
1570 {
1571  pool_base pb = get_pool();
1572 
1573  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1574 
1575  flat_transaction::run(pb, [&] {
1576  internal_insert(
1577  idx, single_element_iterator<value_type>(&value, 0),
1578  single_element_iterator<value_type>(&value, count));
1579  });
1580 
1581  return iterator(_data.get() + static_cast<difference_type>(idx));
1582 }
1583 
1618 template <typename T>
1619 template <typename InputIt,
1620  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1621  InputIt>::type *>
1622 typename vector<T>::iterator
1623 vector<T>::insert(const_iterator pos, InputIt first, InputIt last)
1624 {
1625  pool_base pb = get_pool();
1626 
1627  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1628 
1629  flat_transaction::run(pb, [&] { internal_insert(idx, first, last); });
1630 
1631  return iterator(&_data[static_cast<difference_type>(idx)]);
1632 }
1633 
1662 template <typename T>
1663 typename vector<T>::iterator
1664 vector<T>::insert(const_iterator pos, std::initializer_list<value_type> ilist)
1665 {
1666  return insert(pos, ilist.begin(), ilist.end());
1667 }
1668 
1696 template <typename T>
1697 template <class... Args>
1698 typename vector<T>::iterator
1699 vector<T>::emplace(const_iterator pos, Args &&... args)
1700 {
1701  pool_base pb = get_pool();
1702 
1703  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1704 
1705  flat_transaction::run(pb, [&] {
1706  /*
1707  * args might be a reference to underlying array element. This
1708  * reference can be invalidated after internal_insert() call.
1709  * Hence, we must cache value_type object in temp_value.
1710  */
1711  detail::temp_value<value_type,
1712  noexcept(T(std::forward<Args>(args)...))>
1713  tmp(std::forward<Args>(args)...);
1714 
1715  auto &tmp_ref = tmp.get();
1716 
1717  internal_insert(idx, std::make_move_iterator(&tmp_ref),
1718  std::make_move_iterator(&tmp_ref + 1));
1719  });
1720 
1721  return iterator(&_data[static_cast<difference_type>(idx)]);
1722 }
1723 
1746 template <typename T>
1747 template <class... Args>
1748 typename vector<T>::reference
1749 vector<T>::emplace_back(Args &&... args)
1750 {
1751  /*
1752  * emplace() cannot be used here, because emplace_back() doesn't require
1753  * element_type to be MoveAssignable and emplace() uses
1754  * std::move_backward() function.
1755  */
1756  pool_base pb = get_pool();
1757 
1758  flat_transaction::run(pb, [&] {
1759  if (_size == _capacity) {
1760  realloc(get_recommended_capacity(_size + 1));
1761  } else {
1762  add_data_to_tx(size(), 1);
1763  }
1764 
1765  construct_at_end(1, std::forward<Args>(args)...);
1766  });
1767 
1768  return back();
1769 }
1770 
1790 template <typename T>
1791 typename vector<T>::iterator
1792 vector<T>::erase(const_iterator pos)
1793 {
1794  return erase(pos, pos + 1);
1795 }
1796 
1819 template <typename T>
1820 typename vector<T>::iterator
1821 vector<T>::erase(const_iterator first, const_iterator last)
1822 {
1823  size_type idx = static_cast<size_type>(
1824  std::distance(const_iterator(_data.get()), first));
1825  size_type count = static_cast<size_type>(std::distance(first, last));
1826 
1827  if (count == 0)
1828  return iterator(&_data[static_cast<difference_type>(idx)]);
1829 
1830  pool_base pb = get_pool();
1831 
1832  flat_transaction::run(pb, [&] {
1833  if (!std::is_trivially_destructible<T>::value ||
1834  idx + count < _size)
1835  add_data_to_tx(idx, _size - idx);
1836 
1837  pointer move_begin =
1838  &_data[static_cast<difference_type>(idx + count)];
1839  pointer move_end = &_data[static_cast<difference_type>(size())];
1840  pointer dest = &_data[static_cast<difference_type>(idx)];
1841 
1842  std::move(move_begin, move_end, dest);
1843 
1844  _size -= count;
1845  });
1846 
1847  return iterator(&_data[static_cast<difference_type>(idx)]);
1848 }
1849 
1865 template <typename T>
1866 void
1867 vector<T>::push_back(const value_type &value)
1868 {
1869  emplace_back(value);
1870 }
1871 
1888 template <typename T>
1889 void
1890 vector<T>::push_back(value_type &&value)
1891 {
1892  emplace_back(std::move(value));
1893 }
1894 
1905 template <typename T>
1906 void
1908 {
1909  if (empty())
1910  return;
1911 
1912  pool_base pb = get_pool();
1913  flat_transaction::run(pb, [&] { shrink(size() - 1); });
1914 }
1915 
1932 template <typename T>
1933 void
1934 vector<T>::resize(size_type count)
1935 {
1936  pool_base pb = get_pool();
1937  flat_transaction::run(pb, [&] {
1938  if (count <= _size)
1939  shrink(count);
1940  else {
1941  if (_capacity < count)
1942  realloc(count);
1943  construct_at_end(count - _size);
1944  }
1945  });
1946 }
1947 
1965 template <typename T>
1966 void
1967 vector<T>::resize(size_type count, const value_type &value)
1968 {
1969  if (_capacity == count)
1970  return;
1971 
1972  pool_base pb = get_pool();
1973  flat_transaction::run(pb, [&] {
1974  if (count <= _size)
1975  shrink(count);
1976  else {
1977  if (_capacity < count)
1978  realloc(count);
1979  construct_at_end(count - _size, value);
1980  }
1981  });
1982 }
1983 
1987 template <typename T>
1988 void
1990 {
1991  pool_base pb = get_pool();
1992  flat_transaction::run(pb, [&] {
1993  std::swap(this->_data, other._data);
1994  std::swap(this->_size, other._size);
1995  std::swap(this->_capacity, other._capacity);
1996  });
1997 }
1998 
2005 template <typename T>
2006 void
2007 vector<T>::for_each_ptr(for_each_ptr_function func)
2008 {
2009  func(_data);
2010 }
2011 
2029 template <typename T>
2030 void
2031 vector<T>::alloc(size_type capacity_new)
2032 {
2033  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2034  assert(_data == nullptr);
2035  assert(_size == 0);
2036 
2037  if (capacity_new > max_size())
2038  throw std::length_error("New capacity exceeds max size.");
2039 
2040  _capacity = capacity_new;
2041 
2042  if (capacity_new == 0)
2043  return;
2044 
2045  /*
2046  * We need to cache pmemobj_tx_alloc return value and only after that
2047  * assign it to _data, because when pmemobj_tx_alloc fails, it aborts
2048  * transaction.
2049  */
2050  persistent_ptr<T[]> res =
2051  pmemobj_tx_alloc(sizeof(value_type) * capacity_new,
2052  detail::type_num<value_type>());
2053 
2054  if (res == nullptr) {
2055  if (errno == ENOMEM)
2057  "Failed to allocate persistent memory object")
2058  .with_pmemobj_errormsg();
2059  else
2061  "Failed to allocate persistent memory object")
2062  .with_pmemobj_errormsg();
2063  }
2064 
2065  _data = res;
2066 }
2067 
2074 template <typename T>
2075 void
2077 {
2078  if (nullptr == pmemobj_pool_by_ptr(this))
2079  throw pmem::pool_error("Invalid pool handle.");
2080 }
2081 
2089 template <typename T>
2090 void
2092 {
2093  if (pmemobj_tx_stage() != TX_STAGE_WORK)
2095  "Function called out of transaction scope.");
2096 }
2097 
2116 template <typename T>
2117 template <typename... Args>
2118 void
2119 vector<T>::construct_at_end(size_type count, Args &&... args)
2120 {
2121  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2122  assert(_capacity >= count + _size);
2123 
2124  pointer dest = _data.get() + size();
2125  const_pointer end = dest + count;
2126  for (; dest != end; ++dest)
2127  detail::create<value_type, Args...>(
2128  dest, std::forward<Args>(args)...);
2129  _size += count;
2130 }
2131 
2154 template <typename T>
2155 template <typename InputIt,
2156  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2157  InputIt>::type *>
2158 void
2159 vector<T>::construct_at_end(InputIt first, InputIt last)
2160 {
2161  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2162  difference_type range_size = std::distance(first, last);
2163  assert(range_size >= 0);
2164  assert(_capacity >= static_cast<size_type>(range_size) + _size);
2165 
2166  pointer dest = _data.get() + size();
2167  _size += static_cast<size_type>(range_size);
2168  while (first != last)
2169  detail::create<value_type>(dest++, *first++);
2170 }
2171 
2187 template <typename T>
2188 void
2190 {
2191  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2192 
2193  if (_data != nullptr) {
2194  shrink(0);
2195  if (pmemobj_tx_free(*_data.raw_ptr()) != 0)
2197  "failed to delete persistent memory object")
2198  .with_pmemobj_errormsg();
2199  _data = nullptr;
2200  _capacity = 0;
2201  }
2202 }
2203 
2211 template <typename T>
2212 pool_base
2214 {
2215  return pmem::obj::pool_by_vptr(this);
2216 }
2217 
2225 template <typename T>
2226 void
2227 vector<T>::move_elements_backward(pointer first, pointer last, pointer d_last)
2228 {
2229  while (first != last && d_last >= cend())
2230  detail::create<value_type>(--d_last, std::move(*(--last)));
2231 
2232  if (first != last)
2233  std::move_backward(first, last, d_last);
2234 }
2235 
2243 template <typename T>
2244 template <typename InputIt>
2245 void
2246 vector<T>::construct_or_assign(size_type idx, InputIt first, InputIt last)
2247 {
2248  auto count = static_cast<size_type>(std::distance(first, last));
2249  auto dest = _data.get() + idx;
2250  auto initialized_slots = static_cast<size_type>(cend() - dest);
2251 
2252  /* Assign new elements to initialized memory */
2253  if (dest < cend())
2254  dest = std::copy_n(first, (std::min)(initialized_slots, count),
2255  dest);
2256 
2257  std::advance(first, (std::min)(initialized_slots, count));
2258 
2259  /* Rest of the elements will be created in uninitialized memory */
2260  while (first != last)
2261  detail::create<value_type>(dest++, *first++);
2262 
2263  _size += count;
2264 }
2265 
2286 template <typename T>
2287 template <typename InputIt>
2288 void
2289 vector<T>::internal_insert(size_type idx, InputIt first, InputIt last)
2290 {
2291  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2292 
2293  auto count = static_cast<size_type>(std::distance(first, last));
2294 
2295  if (_capacity >= size() + count) {
2296  pointer dest = _data.get() +
2297  static_cast<difference_type>(size() + count);
2298  pointer begin = _data.get() + static_cast<difference_type>(idx);
2299  pointer end =
2300  _data.get() + static_cast<difference_type>(size());
2301 
2302  add_data_to_tx(idx, size() - idx + count);
2303 
2304  /* Make a gap for new elements */
2305  move_elements_backward(begin, end, dest);
2306 
2307  /* Construct new elements in the gap */
2308  construct_or_assign(idx, first, last);
2309  } else {
2310  /*
2311  * XXX: future optimization: we don't have to snapshot data
2312  * which we will copy (only snapshot for move)
2313  */
2314  add_data_to_tx(0, _size);
2315 
2316  auto old_data = _data;
2317  auto old_size = _size;
2318  pointer old_begin = _data.get();
2319  pointer old_mid =
2320  _data.get() + static_cast<difference_type>(idx);
2321  pointer old_end =
2322  _data.get() + static_cast<difference_type>(size());
2323 
2324  _data = nullptr;
2325  _size = _capacity = 0;
2326 
2327  alloc(get_recommended_capacity(old_size + count));
2328 
2329  /* Move range before the idx to new array */
2330  construct_at_end(std::make_move_iterator(old_begin),
2331  std::make_move_iterator(old_mid));
2332 
2333  /* Insert (first, last) range to the new array */
2334  construct_at_end(first, last);
2335 
2336  /* Move remaining element to the new array */
2337  construct_at_end(std::make_move_iterator(old_mid),
2338  std::make_move_iterator(old_end));
2339 
2340  /* destroy and free old data */
2341  for (size_type i = 0; i < old_size; ++i)
2342  detail::destroy<value_type>(
2343  old_data[static_cast<difference_type>(i)]);
2344  if (pmemobj_tx_free(old_data.raw()) != 0)
2346  "failed to delete persistent memory object")
2347  .with_pmemobj_errormsg();
2348  }
2349 }
2350 
2369 template <typename T>
2370 void
2371 vector<T>::realloc(size_type capacity_new)
2372 {
2373  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2374 
2375  /*
2376  * If _data == nullptr this object has never allocated any memory
2377  * so we need to behave as alloc instead.
2378  */
2379  if (_data == nullptr)
2380  return alloc(capacity_new);
2381 
2382  /*
2383  * XXX: future optimization: we don't have to snapshot data
2384  * which we will not overwrite
2385  */
2386  add_data_to_tx(0, _size);
2387 
2388  auto old_data = _data;
2389  auto old_size = _size;
2390  pointer old_begin = _data.get();
2391  pointer old_end = capacity_new < _size
2392  ? &_data[static_cast<difference_type>(capacity_new)]
2393  : &_data[static_cast<difference_type>(size())];
2394 
2395  _data = nullptr;
2396  _size = _capacity = 0;
2397 
2398  alloc(capacity_new);
2399 
2400  construct_at_end(std::make_move_iterator(old_begin),
2401  std::make_move_iterator(old_end));
2402 
2403  /* destroy and free old data */
2404  for (size_type i = 0; i < old_size; ++i)
2405  detail::destroy<value_type>(
2406  old_data[static_cast<difference_type>(i)]);
2407  if (pmemobj_tx_free(old_data.raw()) != 0)
2409  "failed to delete persistent memory object")
2410  .with_pmemobj_errormsg();
2411 }
2412 
2419 template <typename T>
2420 typename vector<T>::size_type
2421 vector<T>::get_recommended_capacity(size_type at_least) const
2422 {
2423  return detail::next_pow_2(at_least);
2424 }
2425 
2442 template <typename T>
2443 void
2444 vector<T>::shrink(size_type size_new)
2445 {
2446  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2447  assert(size_new <= _size);
2448 
2449  if (!std::is_trivially_destructible<T>::value)
2450  add_data_to_tx(size_new, _size - size_new);
2451 
2452  for (size_type i = size_new; i < _size; ++i)
2453  detail::destroy<value_type>(
2454  _data[static_cast<difference_type>(i)]);
2455  _size = size_new;
2456 }
2457 
2467 template <typename T>
2468 void
2469 vector<T>::add_data_to_tx(size_type idx_first, size_type num)
2470 {
2471  assert(idx_first + num <= capacity());
2472 
2473 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2474  /* Make sure that only data allocated by this vector is accessed */
2475  assert(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_data.get() + idx_first,
2476  num * sizeof(T)) == 0);
2477 #endif
2478 
2479  auto initialized_num = size() - idx_first;
2480 
2481  /* Snapshot elements in range [idx_first,size()) */
2482  detail::conditional_add_to_tx(_data.get() + idx_first,
2483  (std::min)(initialized_num, num),
2484  POBJ_XADD_ASSUME_INITIALIZED);
2485 
2486  if (num > initialized_num) {
2487  /* Elements after size() do not have to be snapshotted */
2488  detail::conditional_add_to_tx(_data.get() + size(),
2489  num - initialized_num,
2490  POBJ_XADD_NO_SNAPSHOT);
2491  }
2492 }
2493 
2505 template <typename T>
2506 bool
2507 operator==(const vector<T> &lhs, const vector<T> &rhs)
2508 {
2509  return lhs.size() == rhs.size() &&
2510  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2511 }
2512 
2524 template <typename T>
2525 bool
2526 operator!=(const vector<T> &lhs, const vector<T> &rhs)
2527 {
2528  return !(lhs == rhs);
2529 }
2530 
2541 template <typename T>
2542 bool
2543 operator<(const vector<T> &lhs, const vector<T> &rhs)
2544 {
2545  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2546  rhs.end());
2547 }
2548 
2559 template <typename T>
2560 bool
2561 operator<=(const vector<T> &lhs, const vector<T> &rhs)
2562 {
2563  return !(rhs < lhs);
2564 }
2565 
2577 template <typename T>
2578 bool
2579 operator>(const vector<T> &lhs, const vector<T> &rhs)
2580 {
2581  return rhs < lhs;
2582 }
2583 
2594 template <typename T>
2595 bool
2596 operator>=(const vector<T> &lhs, const vector<T> &rhs)
2597 {
2598  return !(lhs < rhs);
2599 }
2600 
2612 template <typename T>
2613 bool
2614 operator==(const vector<T> &lhs, const std::vector<T> &rhs)
2615 {
2616  return lhs.size() == rhs.size() &&
2617  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2618 }
2619 
2631 template <typename T>
2632 bool
2633 operator!=(const vector<T> &lhs, const std::vector<T> &rhs)
2634 {
2635  return !(lhs == rhs);
2636 }
2637 
2648 template <typename T>
2649 bool
2650 operator<(const vector<T> &lhs, const std::vector<T> &rhs)
2651 {
2652  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2653  rhs.end());
2654 }
2655 
2666 template <typename T>
2667 bool
2668 operator<=(const vector<T> &lhs, const std::vector<T> &rhs)
2669 {
2670  return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2671  lhs.begin(), lhs.end()));
2672 }
2673 
2685 template <typename T>
2686 bool
2687 operator>(const vector<T> &lhs, const std::vector<T> &rhs)
2688 {
2689  return !(lhs <= rhs);
2690 }
2691 
2702 template <typename T>
2703 bool
2704 operator>=(const vector<T> &lhs, const std::vector<T> &rhs)
2705 {
2706  return !(lhs < rhs);
2707 }
2708 
2720 template <typename T>
2721 bool
2722 operator==(const std::vector<T> &lhs, const vector<T> &rhs)
2723 {
2724  return rhs == lhs;
2725 }
2726 
2738 template <typename T>
2739 bool
2740 operator!=(const std::vector<T> &lhs, const vector<T> &rhs)
2741 {
2742  return !(lhs == rhs);
2743 }
2744 
2755 template <typename T>
2756 bool
2757 operator<(const std::vector<T> &lhs, const vector<T> &rhs)
2758 {
2759  return rhs > lhs;
2760 }
2761 
2772 template <typename T>
2773 bool
2774 operator<=(const std::vector<T> &lhs, const vector<T> &rhs)
2775 {
2776  return !(rhs < lhs);
2777 }
2778 
2790 template <typename T>
2791 bool
2792 operator>(const std::vector<T> &lhs, const vector<T> &rhs)
2793 {
2794  return rhs < lhs;
2795 }
2796 
2807 template <typename T>
2808 bool
2809 operator>=(const std::vector<T> &lhs, const vector<T> &rhs)
2810 {
2811  return !(lhs < rhs);
2812 }
2813 
2820 template <typename T>
2821 void
2823 {
2824  lhs.swap(rhs);
2825 }
2826 
2827 } /* namespace obj */
2828 
2829 } /* namespace pmem */
2830 
2831 #endif /* LIBPMEMOBJ_CPP_VECTOR_HPP */
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:823
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:42
The non-template pool base class.
Definition: pool.hpp:50
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:50
pmem::obj::vector - persistent container with std::vector compatible interface.
Definition: vector.hpp:41
const_reference front() const
Access the first element.
Definition: vector.hpp:965
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: vector.hpp:1195
const value_type * cdata() const noexcept
Returns const raw pointer to the underlying data.
Definition: vector.hpp:1068
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: vector.hpp:1223
const value_type * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: vector.hpp:1054
vector(vector &&other)
Move constructor.
Definition: vector.hpp:476
void free_data()
Clears the content of a vector and frees all allocated persistent memory for data transactionally.
Definition: vector.hpp:1459
vector(const std::vector< T > &other)
Copy constructor.
Definition: vector.hpp:530
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: vector.hpp:899
size_type size() const noexcept
Definition: vector.hpp:1348
const_reference operator[](size_type n) const
Access element at specific index.
Definition: vector.hpp:935
vector & operator=(const std::vector< T > &other)
Copy assignment operator.
Definition: vector.hpp:606
slice< pointer > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: vector.hpp:1243
void check_pmem()
Private helper function.
Definition: vector.hpp:2076
void assign(InputIt first, InputIt last)
Replaces the contents with copies of those in the range [first, last) transactionally.
Definition: vector.hpp:689
const_reference at(size_type n) const
Access element at specific index with bounds checking.
Definition: vector.hpp:877
reference back()
Access the last element and add this element to a transaction.
Definition: vector.hpp:994
void construct_at_end(size_type count, Args &&... args)
Private helper function.
Definition: vector.hpp:2119
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: vector.hpp:1322
void assign(const std::vector< T > &other)
Copy assignment method.
Definition: vector.hpp:819
iterator begin()
Returns an iterator to the beginning.
Definition: vector.hpp:1080
void check_tx_stage_work()
Private helper function.
Definition: vector.hpp:2091
void assign(vector &&other)
Move assignment method.
Definition: vector.hpp:786
void pop_back()
Removes the last element of the container transactionally.
Definition: vector.hpp:1907
vector(InputIt first, InputIt last)
Constructs the container with the contents of the range [first, last).
Definition: vector.hpp:415
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: vector.hpp:919
reference front()
Access the first element and add this element to a transaction.
Definition: vector.hpp:950
vector(size_type count, const value_type &value)
Constructs the container with count copies of elements with value value.
Definition: vector.hpp:349
void alloc(size_type size)
Private helper function.
Definition: vector.hpp:2031
reference at(size_type n)
Access element at specific index with bounds checking and add it to a transaction.
Definition: vector.hpp:855
pool_base get_pool() const
Private helper function.
Definition: vector.hpp:2213
void resize(size_type count)
Resizes the container to count elements transactionally.
Definition: vector.hpp:1934
void swap(vector &other)
Exchanges the contents of the container with other transactionally.
Definition: vector.hpp:1989
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: vector.hpp:1182
iterator emplace(const_iterator pos, Args &&... args)
Inserts a new element into the container directly before pos.
Definition: vector.hpp:1699
void shrink_to_fit()
Requests transactional removal of unused capacity.
Definition: vector.hpp:1419
iterator erase(const_iterator pos)
Removes the element at pos.
Definition: vector.hpp:1792
const_reference cfront() const
Access the first element.
Definition: vector.hpp:979
reference emplace_back(Args &&... args)
Appends a new element to the end of the container.
Definition: vector.hpp:1749
void dealloc()
Private helper function.
Definition: vector.hpp:2189
const_reference cback() const
Access the last element.
Definition: vector.hpp:1024
void clear()
Clears the content of a vector transactionally.
Definition: vector.hpp:1439
iterator insert(const_iterator pos, const T &value)
Inserts value before pos in the container transactionally.
Definition: vector.hpp:1494
void construct_or_assign(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2246
vector(const vector &other)
Copy constructor.
Definition: vector.hpp:445
void for_each_ptr(for_each_ptr_function func)
Iterates over all internal pointers and executes a callback function on each of them.
Definition: vector.hpp:2007
const_reference back() const
Access the last element.
Definition: vector.hpp:1010
void construct_at_end(InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2159
vector(std::initializer_list< T > init)
Constructs the container with the contents of the initializer list init.
Definition: vector.hpp:506
void assign(const vector &other)
Copy assignment method.
Definition: vector.hpp:767
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: vector.hpp:1156
vector & operator=(vector &&other)
Move assignment operator.
Definition: vector.hpp:567
void realloc(size_type size)
Private helper function.
Definition: vector.hpp:2371
vector()
Default constructor.
Definition: vector.hpp:320
~vector()
Destructor.
Definition: vector.hpp:832
vector & operator=(std::initializer_list< T > ilist)
Replaces the contents with those identified by initializer list ilist transactionally.
Definition: vector.hpp:585
size_type capacity() const noexcept
Definition: vector.hpp:1398
size_type get_recommended_capacity(size_type at_least) const
Private helper function.
Definition: vector.hpp:2421
void reserve(size_type capacity_new)
Increases the capacity of the vector to capacity_new transactionally.
Definition: vector.hpp:1384
void assign(std::initializer_list< T > ilist)
Replaces the contents with the elements from the initializer list ilist transactionally.
Definition: vector.hpp:749
void internal_insert(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2289
value_type * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: vector.hpp:1040
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: vector.hpp:1338
void shrink(size_type size_new)
Private helper function.
Definition: vector.hpp:2444
void add_data_to_tx(size_type idx_first, size_type num)
Private helper function.
Definition: vector.hpp:2469
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: vector.hpp:1106
void move_elements_backward(pointer first, pointer last, pointer d_last)
Private helper function.
Definition: vector.hpp:2227
constexpr size_type max_size() const noexcept
Definition: vector.hpp:1359
void push_back(const T &value)
Appends the given element value to the end of the container transactionally.
Definition: vector.hpp:1867
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: vector.hpp:1144
iterator end()
Returns an iterator to past the end.
Definition: vector.hpp:1118
vector & operator=(const vector &other)
Copy assignment operator.
Definition: vector.hpp:548
vector(size_type count)
Constructs the container with count copies of T default constructed values.
Definition: vector.hpp:378
Custom pool error class.
Definition: pexceptions.hpp:45
Custom transaction error class.
Definition: pexceptions.hpp:119
Custom transaction error class.
Definition: pexceptions.hpp:158
Custom out of memory error class.
Definition: pexceptions.hpp:138
Custom transaction error class.
Definition: pexceptions.hpp:176
Commonly used functionality.
Iterators for contiguous persistent containers.
Common iterator traits.
Functions for destroying arrays.
Persistent_ptr transactional allocation functions for objects.
uint64_t next_pow_2(uint64_t v)
Round up to the next lowest power of 2.
Definition: common.hpp:214
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:779
persistent_ptr< T > operator-(persistent_ptr< T > const &lhs, std::ptrdiff_t s)
Subtraction operator for persistent pointers.
Definition: persistent_ptr.hpp:822
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:748
void swap(vector< T > &lhs, vector< T > &rhs)
Swaps the contents of lhs and rhs.
Definition: vector.hpp:2822
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:769
p< T > & operator++(p< T > &pp)
Prefix increment operator overload.
Definition: pext.hpp:48
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:789
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:536
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:849
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
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:420
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:759
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:799
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:909
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:829
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Convenience extensions for the resides on pmem property template.
Interface to access sequence of objects.
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:47
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:192
C++ pmemobj transactions.
Libpmemobj C++ utils.