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