PMDK C++ bindings  1.9
This is the C++ bindings documentation for PMDK's libpmemobj.
vector.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018-2021, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_CPP_VECTOR_HPP
39 #define LIBPMEMOBJ_CPP_VECTOR_HPP
40 
48 #include <libpmemobj++/pext.hpp>
49 #include <libpmemobj++/slice.hpp>
51 #include <libpmemobj/base.h>
52 
53 #include <algorithm>
54 #include <cassert>
55 #include <utility>
56 #include <vector>
57 
58 namespace pmem
59 {
60 
61 namespace obj
62 {
63 
68 template <typename T>
69 class vector {
70 public:
71  /* Member types */
72  using value_type = T;
73  using size_type = std::size_t;
74  using difference_type = std::ptrdiff_t;
75  using reference = value_type &;
76  using const_reference = const value_type &;
77  using pointer = value_type *;
78  using const_pointer = const value_type *;
80  using const_iterator = const_pointer;
81  using reverse_iterator = std::reverse_iterator<iterator>;
82  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
85  /* func argument type definition for 'for_each_ptr' method */
86  using for_each_ptr_function =
87  std::function<void(persistent_ptr_base &)>;
88 
89  /* Constructors */
90  vector();
91  vector(size_type count, const value_type &value);
92  explicit vector(size_type count);
93  template <typename InputIt,
94  typename std::enable_if<
96  InputIt>::type * = nullptr>
97  vector(InputIt first, InputIt last);
98  vector(const vector &other);
99  vector(vector &&other);
100  vector(std::initializer_list<T> init);
101  vector(const std::vector<T> &other);
102 
103  /* Assign operators */
104  vector &operator=(const vector &other);
106  vector &operator=(std::initializer_list<T> ilist);
107  vector &operator=(const std::vector<T> &other);
108 
109  /* Assign methods */
110  void assign(size_type count, const T &value);
111  template <typename InputIt,
112  typename std::enable_if<
114  InputIt>::type * = nullptr>
115  void assign(InputIt first, InputIt last);
116  void assign(std::initializer_list<T> ilist);
117  void assign(const vector &other);
118  void assign(vector &&other);
119  void assign(const std::vector<T> &other);
120 
121  /* Destructor */
123 
124  /* Element access */
125  reference at(size_type n);
126  const_reference at(size_type n) const;
127  const_reference const_at(size_type n) const;
128  reference operator[](size_type n);
129  const_reference operator[](size_type n) const;
130  reference front();
131  const_reference front() const;
132  const_reference cfront() const;
133  reference back();
134  const_reference back() const;
135  const_reference cback() const;
136  value_type *data();
137  const value_type *data() const noexcept;
138  const value_type *cdata() const noexcept;
139 
140  /* Iterators */
142  const_iterator begin() const noexcept;
143  const_iterator cbegin() const noexcept;
145  const_iterator end() const noexcept;
146  const_iterator cend() const noexcept;
147  reverse_iterator rbegin();
148  const_reverse_iterator rbegin() const noexcept;
149  const_reverse_iterator crbegin() const noexcept;
150  reverse_iterator rend();
151  const_reverse_iterator rend() const noexcept;
152  const_reverse_iterator crend() const noexcept;
153 
154  /* Range */
155  slice<pointer> range(size_type start, size_type n);
156  slice<range_snapshotting_iterator> range(size_type start, size_type n,
157  size_type snapshot_size);
158  slice<const_iterator> range(size_type start, size_type n) const;
159  slice<const_iterator> crange(size_type start, size_type n) const;
160  void for_each_ptr(for_each_ptr_function func);
161 
162  /* Capacity */
163  constexpr bool empty() const noexcept;
164  size_type size() const noexcept;
165  constexpr size_type max_size() const noexcept;
166  void reserve(size_type capacity_new);
167  size_type capacity() const noexcept;
169 
170  /* Modifiers */
171  void clear();
172  void free_data();
173  iterator insert(const_iterator pos, const T &value);
174  iterator insert(const_iterator pos, T &&value);
175  iterator insert(const_iterator pos, size_type count, const T &value);
176  template <typename InputIt,
177  typename std::enable_if<
178  detail::is_input_iterator<InputIt>::value,
179  InputIt>::type * = nullptr>
180  iterator insert(const_iterator pos, InputIt first, InputIt last);
181  iterator insert(const_iterator pos, std::initializer_list<T> ilist);
182  template <class... Args>
183  iterator emplace(const_iterator pos, Args &&... args);
184  template <class... Args>
185  reference emplace_back(Args &&... args);
186  iterator erase(const_iterator pos);
187  iterator erase(const_iterator first, const_iterator last);
188  void push_back(const T &value);
189  void push_back(T &&value);
190  void pop_back();
191  void resize(size_type count);
192  void resize(size_type count, const value_type &value);
193  void swap(vector &other);
194 
195 private:
196  /* helper iterator */
197  template <typename P>
198  struct single_element_iterator {
199  using iterator_category = std::input_iterator_tag;
200  using value_type = P;
201  using difference_type = std::ptrdiff_t;
202  using pointer = const P *;
203  using reference = const P &;
204 
205  const P *ptr;
206  std::size_t count;
207 
208  single_element_iterator(const P *ptr, std::size_t count = 0)
209  : ptr(ptr), count(count)
210  {
211  }
212 
213  reference operator*()
214  {
215  return *ptr;
216  }
217 
218  pointer operator->()
219  {
220  return ptr;
221  }
222 
223  single_element_iterator &
224  operator++()
225  {
226  count++;
227  return *this;
228  }
229 
230  single_element_iterator
231  operator++(int)
232  {
233  single_element_iterator tmp =
234  single_element_iterator(ptr, count);
235  count++;
236  return tmp;
237  }
238 
239  difference_type
240  operator-(const single_element_iterator &rhs)
241  {
242  return count - rhs.count;
243  }
244 
245  bool
246  operator!=(const single_element_iterator &rhs)
247  {
248  return ptr != rhs.ptr || count != rhs.count;
249  }
250  };
251 
252  /* helper functions */
253  void alloc(size_type size);
254  void check_pmem();
256  template <typename... Args>
257  void construct_at_end(size_type count, Args &&... args);
258  template <typename InputIt,
259  typename std::enable_if<
261  InputIt>::type * = nullptr>
262  void construct_at_end(InputIt first, InputIt last);
263  void dealloc();
264  pool_base get_pool() const noexcept;
265  template <typename InputIt>
266  void internal_insert(size_type idx, InputIt first, InputIt last);
267  void realloc(size_type size);
268  size_type get_recommended_capacity(size_type at_least) const;
269  void shrink(size_type size_new);
270  void add_data_to_tx(size_type idx_first, size_type num);
271  template <typename InputIt>
272  void construct_or_assign(size_type idx, InputIt first, InputIt last);
273  void move_elements_backward(pointer first, pointer last,
274  pointer d_last);
275 
276  p<size_type> _size;
277  p<size_type> _capacity;
278 
279  /* Underlying array */
280  persistent_ptr<T[]> _data;
281 };
282 
283 /* Non-member swap */
284 template <typename T>
285 void swap(vector<T> &lhs, vector<T> &rhs);
286 
287 /*
288  * Comparison operators between pmem::obj::vector<T> and
289  * pmem::obj::vector<T>
290  */
291 template <typename T>
292 bool operator==(const vector<T> &lhs, const vector<T> &rhs);
293 template <typename T>
294 bool operator!=(const vector<T> &lhs, const vector<T> &rhs);
295 template <typename T>
296 bool operator<(const vector<T> &lhs, const vector<T> &rhs);
297 template <typename T>
298 bool operator<=(const vector<T> &lhs, const vector<T> &rhs);
299 template <typename T>
300 bool operator>(const vector<T> &lhs, const vector<T> &rhs);
301 template <typename T>
302 bool operator>=(const vector<T> &lhs, const vector<T> &rhs);
303 
304 /*
305  * Comparison operators between pmem::obj::vector<T> and
306  * std::vector<T>
307  */
308 template <typename T>
309 bool operator==(const vector<T> &lhs, const std::vector<T> &rhs);
310 template <typename T>
311 bool operator!=(const vector<T> &lhs, const std::vector<T> &rhs);
312 template <typename T>
313 bool operator<(const vector<T> &lhs, const std::vector<T> &rhs);
314 template <typename T>
315 bool operator<=(const vector<T> &lhs, const std::vector<T> &rhs);
316 template <typename T>
317 bool operator>(const vector<T> &lhs, const std::vector<T> &rhs);
318 template <typename T>
319 bool operator>=(const vector<T> &lhs, const std::vector<T> &rhs);
320 
321 /*
322  * Comparison operators between std::vector<T> and
323  * pmem::obj::vector<T>
324  */
325 template <typename T>
326 bool operator==(const std::vector<T> &lhs, const vector<T> &rhs);
327 template <typename T>
328 bool operator!=(const std::vector<T> &lhs, const vector<T> &rhs);
329 template <typename T>
330 bool operator<(const std::vector<T> &lhs, const vector<T> &rhs);
331 template <typename T>
332 bool operator<=(const std::vector<T> &lhs, const vector<T> &rhs);
333 template <typename T>
334 bool operator>(const std::vector<T> &lhs, const vector<T> &rhs);
335 template <typename T>
336 bool operator>=(const std::vector<T> &lhs, const vector<T> &rhs);
337 
347 template <typename T>
349 {
350  check_pmem();
352 
353  _data = nullptr;
354  _size = 0;
355  _capacity = 0;
356 }
357 
376 template <typename T>
377 vector<T>::vector(size_type count, const value_type &value)
378 {
379  check_pmem();
381 
382  _data = nullptr;
383  _size = 0;
384  alloc(count);
385  construct_at_end(count, value);
386 }
387 
405 template <typename T>
406 vector<T>::vector(size_type count)
407 {
408  check_pmem();
410 
411  _data = nullptr;
412  _size = 0;
413  alloc(count);
414  construct_at_end(count);
415 }
416 
439 template <typename T>
440 template <typename InputIt,
441  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
442  InputIt>::type *>
443 vector<T>::vector(InputIt first, InputIt last)
444 {
445  check_pmem();
447 
448  _data = nullptr;
449  _size = 0;
450  alloc(static_cast<size_type>(std::distance(first, last)));
451  construct_at_end(first, last);
452 }
453 
472 template <typename T>
474 {
475  check_pmem();
477 
478  _data = nullptr;
479  _size = 0;
480  alloc(other.capacity());
481  construct_at_end(other.cbegin(), other.cend());
482 }
483 
503 template <typename T>
505 {
506  check_pmem();
508 
509  _data = other._data;
510  _capacity = other.capacity();
511  _size = other.size();
512  other._data = nullptr;
513  other._capacity = other._size = 0;
514 }
515 
533 template <typename T>
534 vector<T>::vector(std::initializer_list<T> init)
535  : vector(init.begin(), init.end())
536 {
537 }
538 
557 template <typename T>
558 vector<T>::vector(const std::vector<T> &other)
559  : vector(other.cbegin(), other.cend())
560 {
561 }
562 
574 template <typename T>
575 vector<T> &
577 {
578  assign(other);
579 
580  return *this;
581 }
582 
593 template <typename T>
594 vector<T> &
596 {
597  assign(std::move(other));
598 
599  return *this;
600 }
601 
611 template <typename T>
612 vector<T> &
613 vector<T>::operator=(std::initializer_list<T> ilist)
614 {
615  assign(ilist.begin(), ilist.end());
616 
617  return *this;
618 }
619 
632 template <typename T>
633 vector<T> &
634 vector<T>::operator=(const std::vector<T> &other)
635 {
636  assign(other);
637 
638  return *this;
639 }
640 
657 template <typename T>
658 void
659 vector<T>::assign(size_type count, const_reference value)
660 {
661  pool_base pb = get_pool();
662 
663  transaction::run(pb, [&] {
664  if (count <= capacity()) {
665  /*
666  * Reallocation is not needed. First, replace old
667  * elements with new ones in range [0, size()).
668  * Depending on count, either call remaining old
669  * elements destructors, or append more new elements.
670  */
671  size_type size_old = _size;
672  add_data_to_tx(0, size_old);
673 
674  std::fill_n(
675  _data.get(),
676  (std::min)(count,
677  static_cast<size_type>(size_old)),
678  value);
679 
680  if (count > size_old) {
681  add_data_to_tx(size_old, count - size_old);
682  construct_at_end(count - size_old, value);
683  } else {
684  shrink(count);
685  }
686  } else {
687  dealloc();
688  alloc(count);
689  construct_at_end(count, value);
690  }
691  });
692 }
693 
712 template <typename T>
713 template <typename InputIt,
714  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
715  InputIt>::type *>
716 void
717 vector<T>::assign(InputIt first, InputIt last)
718 {
719  pool_base pb = get_pool();
720 
721  size_type size_new = static_cast<size_type>(std::distance(first, last));
722 
723  transaction::run(pb, [&] {
724  if (size_new <= capacity()) {
725  /*
726  * Reallocation is not needed. First, replace old
727  * elements with new ones in range [0, size()).
728  * Depending on size_new, either call remaining old
729  * elements destructors, or append more new elements.
730  */
731  size_type size_old = _size;
732  add_data_to_tx(0, size_old);
733 
734  InputIt mid = last;
735  bool growing = size_new > size_old;
736 
737  if (growing) {
738  add_data_to_tx(size_old, size_new - size_old);
739 
740  mid = first;
741  std::advance(mid, size_old);
742  }
743 
744  iterator shrink_to = std::copy(first, mid, &_data[0]);
745 
746  if (growing) {
747  construct_at_end(mid, last);
748  } else {
749  shrink(static_cast<size_type>(std::distance(
750  iterator(&_data[0]), shrink_to)));
751  }
752  } else {
753  dealloc();
754  alloc(size_new);
755  construct_at_end(first, last);
756  }
757  });
758 }
759 
775 template <typename T>
776 void
777 vector<T>::assign(std::initializer_list<T> ilist)
778 {
779  assign(ilist.begin(), ilist.end());
780 }
781 
793 template <typename T>
794 void
796 {
797  if (this != &other)
798  assign(other.cbegin(), other.cend());
799 }
800 
812 template <typename T>
813 void
815 {
816  if (this == &other)
817  return;
818 
819  pool_base pb = get_pool();
820 
821  transaction::run(pb, [&] {
822  dealloc();
823 
824  _data = other._data;
825  _capacity = other._capacity;
826  _size = other._size;
827 
828  other._data = nullptr;
829  other._capacity = other._size = 0;
830  });
831 }
832 
845 template <typename T>
846 void
847 vector<T>::assign(const std::vector<T> &other)
848 {
849  assign(other.cbegin(), other.cend());
850 }
851 
861 template <typename T>
863 {
864  free_data();
865 }
866 
879 template <typename T>
880 typename vector<T>::reference
881 vector<T>::at(size_type n)
882 {
883  if (n >= _size)
884  throw std::out_of_range("vector::at");
885 
886  detail::conditional_add_to_tx(&_data[static_cast<difference_type>(n)],
887  1, POBJ_XADD_ASSUME_INITIALIZED);
888 
889  return _data[static_cast<difference_type>(n)];
890 }
891 
901 template <typename T>
902 typename vector<T>::const_reference
903 vector<T>::at(size_type n) const
904 {
905  if (n >= _size)
906  throw std::out_of_range("vector::at");
907 
908  return _data[static_cast<difference_type>(n)];
909 }
910 
923 template <typename T>
924 typename vector<T>::const_reference
925 vector<T>::const_at(size_type n) const
926 {
927  if (n >= _size)
928  throw std::out_of_range("vector::const_at");
929 
930  return _data[static_cast<difference_type>(n)];
931 }
932 
944 template <typename T>
945 typename vector<T>::reference vector<T>::operator[](size_type n)
946 {
947  detail::conditional_add_to_tx(&_data[static_cast<difference_type>(n)],
948  1, POBJ_XADD_ASSUME_INITIALIZED);
949 
950  return _data[static_cast<difference_type>(n)];
951 }
952 
960 template <typename T>
961 typename vector<T>::const_reference vector<T>::operator[](size_type n) const
962 {
963  return _data[static_cast<difference_type>(n)];
964 }
965 
974 template <typename T>
975 typename vector<T>::reference
977 {
978  detail::conditional_add_to_tx(&_data[0], 1,
979  POBJ_XADD_ASSUME_INITIALIZED);
980 
981  return _data[0];
982 }
983 
989 template <typename T>
990 typename vector<T>::const_reference
992 {
993  return _data[0];
994 }
995 
1003 template <typename T>
1004 typename vector<T>::const_reference
1006 {
1007  return _data[0];
1008 }
1009 
1018 template <typename T>
1019 typename vector<T>::reference
1021 {
1022  detail::conditional_add_to_tx(
1023  &_data[static_cast<difference_type>(size() - 1)], 1,
1024  POBJ_XADD_ASSUME_INITIALIZED);
1025 
1026  return _data[static_cast<difference_type>(size() - 1)];
1027 }
1028 
1034 template <typename T>
1035 typename vector<T>::const_reference
1037 {
1038  return _data[static_cast<difference_type>(size() - 1)];
1039 }
1040 
1048 template <typename T>
1049 typename vector<T>::const_reference
1051 {
1052  return _data[static_cast<difference_type>(size() - 1)];
1053 }
1054 
1064 template <typename T>
1065 typename vector<T>::value_type *
1067 {
1068  add_data_to_tx(0, _size);
1069 
1070  return _data.get();
1071 }
1072 
1078 template <typename T>
1079 const typename vector<T>::value_type *
1080 vector<T>::data() const noexcept
1081 {
1082  return _data.get();
1083 }
1084 
1092 template <typename T>
1093 const typename vector<T>::value_type *
1094 vector<T>::cdata() const noexcept
1095 {
1096  return _data.get();
1097 }
1098 
1104 template <typename T>
1105 typename vector<T>::iterator
1107 {
1108  return iterator(_data.get());
1109 }
1110 
1116 template <typename T>
1117 typename vector<T>::const_iterator
1118 vector<T>::begin() const noexcept
1119 {
1120  return const_iterator(_data.get());
1121 }
1122 
1130 template <typename T>
1131 typename vector<T>::const_iterator
1132 vector<T>::cbegin() const noexcept
1133 {
1134  return const_iterator(_data.get());
1135 }
1136 
1142 template <typename T>
1143 typename vector<T>::iterator
1145 {
1146  return iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1147 }
1148 
1154 template <typename T>
1155 typename vector<T>::const_iterator
1156 vector<T>::end() const noexcept
1157 {
1158  return const_iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1159 }
1160 
1168 template <typename T>
1169 typename vector<T>::const_iterator
1170 vector<T>::cend() const noexcept
1171 {
1172  return const_iterator(_data.get() + static_cast<std::ptrdiff_t>(_size));
1173 }
1174 
1180 template <typename T>
1181 typename vector<T>::reverse_iterator
1183 {
1184  return reverse_iterator(end());
1185 }
1186 
1192 template <typename T>
1193 typename vector<T>::const_reverse_iterator
1194 vector<T>::rbegin() const noexcept
1195 {
1196  return const_reverse_iterator(cend());
1197 }
1198 
1206 template <typename T>
1207 typename vector<T>::const_reverse_iterator
1208 vector<T>::crbegin() const noexcept
1209 {
1210  return const_reverse_iterator(cend());
1211 }
1212 
1219 template <typename T>
1220 typename vector<T>::reverse_iterator
1222 {
1223  return reverse_iterator(begin());
1224 }
1225 
1232 template <typename T>
1233 typename vector<T>::const_reverse_iterator
1234 vector<T>::rend() const noexcept
1235 {
1236  return const_reverse_iterator(cbegin());
1237 }
1238 
1247 template <typename T>
1248 typename vector<T>::const_reverse_iterator
1249 vector<T>::crend() const noexcept
1250 {
1251  return const_reverse_iterator(cbegin());
1252 }
1253 
1267 template <typename T>
1269 vector<T>::range(size_type start, size_type n)
1270 {
1271  if (start + n > size())
1272  throw std::out_of_range("vector::range");
1273 
1274  detail::conditional_add_to_tx(cdata() + start, n,
1275  POBJ_XADD_ASSUME_INITIALIZED);
1276 
1277  return {_data.get() + start, _data.get() + start + n};
1278 }
1279 
1295 template <typename T>
1297 vector<T>::range(size_type start, size_type n, size_type snapshot_size)
1298 {
1299  if (start + n > size())
1300  throw std::out_of_range("vector::range");
1301 
1302  if (snapshot_size > n)
1303  snapshot_size = n;
1304 
1305  return {range_snapshotting_iterator(_data.get() + start,
1306  _data.get() + start, n,
1307  snapshot_size),
1308  range_snapshotting_iterator(_data.get() + start + n,
1309  _data.get() + start, n,
1310  snapshot_size)};
1311 }
1312 
1324 template <typename T>
1326 vector<T>::range(size_type start, size_type n) const
1327 {
1328  if (start + n > size())
1329  throw std::out_of_range("vector::range");
1330 
1331  return {const_iterator(cdata() + start),
1332  const_iterator(cdata() + start + n)};
1333 }
1334 
1346 template <typename T>
1348 vector<T>::crange(size_type start, size_type n) const
1349 {
1350  if (start + n > size())
1351  throw std::out_of_range("vector::crange");
1352 
1353  return {const_iterator(cdata() + start),
1354  const_iterator(cdata() + start + n)};
1355 }
1356 
1362 template <typename T>
1363 constexpr bool
1364 vector<T>::empty() const noexcept
1365 {
1366  return _size == 0;
1367 }
1368 
1372 template <typename T>
1373 typename vector<T>::size_type
1374 vector<T>::size() const noexcept
1375 {
1376  return _size;
1377 }
1378 
1383 template <typename T>
1384 constexpr typename vector<T>::size_type
1385 vector<T>::max_size() const noexcept
1386 {
1387  return PMEMOBJ_MAX_ALLOC_SIZE / sizeof(value_type);
1388 }
1389 
1408 template <typename T>
1409 void
1410 vector<T>::reserve(size_type capacity_new)
1411 {
1412  if (capacity_new <= _capacity)
1413  return;
1414 
1415  pool_base pb = get_pool();
1416  transaction::run(pb, [&] { realloc(capacity_new); });
1417 }
1418 
1422 template <typename T>
1423 typename vector<T>::size_type
1424 vector<T>::capacity() const noexcept
1425 {
1426  return _capacity;
1427 }
1428 
1443 template <typename T>
1444 void
1446 {
1447  size_type capacity_new = size();
1448  if (capacity() == capacity_new)
1449  return;
1450 
1451  pool_base pb = get_pool();
1452  transaction::run(pb, [&] { realloc(capacity_new); });
1453 }
1454 
1463 template <typename T>
1464 void
1466 {
1467  pool_base pb = get_pool();
1468  transaction::run(pb, [&] { shrink(0); });
1469 }
1470 
1483 template <typename T>
1484 void
1486 {
1487  if (_data == nullptr)
1488  return;
1489 
1490  pool_base pb = get_pool();
1491  transaction::run(pb, [&] { dealloc(); });
1492 }
1493 
1518 template <typename T>
1519 typename vector<T>::iterator
1520 vector<T>::insert(const_iterator pos, const value_type &value)
1521 {
1522  return insert(pos, 1, value);
1523 }
1524 
1549 template <typename T>
1550 typename vector<T>::iterator
1551 vector<T>::insert(const_iterator pos, value_type &&value)
1552 {
1553  pool_base pb = get_pool();
1554 
1555  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1556 
1557  transaction::run(pb, [&] {
1558  internal_insert(idx, std::make_move_iterator(&value),
1559  std::make_move_iterator(&value + 1));
1560  });
1561 
1562  return iterator(&_data[static_cast<difference_type>(idx)]);
1563 }
1564 
1593 template <typename T>
1594 typename vector<T>::iterator
1595 vector<T>::insert(const_iterator pos, size_type count, const value_type &value)
1596 {
1597  pool_base pb = get_pool();
1598 
1599  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1600 
1601  transaction::run(pb, [&] {
1602  internal_insert(
1603  idx, single_element_iterator<value_type>(&value, 0),
1604  single_element_iterator<value_type>(&value, count));
1605  });
1606 
1607  return iterator(_data.get() + static_cast<difference_type>(idx));
1608 }
1609 
1644 template <typename T>
1645 template <typename InputIt,
1646  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1647  InputIt>::type *>
1648 typename vector<T>::iterator
1649 vector<T>::insert(const_iterator pos, InputIt first, InputIt last)
1650 {
1651  pool_base pb = get_pool();
1652 
1653  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1654 
1655  transaction::run(pb, [&] { internal_insert(idx, first, last); });
1656 
1657  return iterator(&_data[static_cast<difference_type>(idx)]);
1658 }
1659 
1688 template <typename T>
1689 typename vector<T>::iterator
1690 vector<T>::insert(const_iterator pos, std::initializer_list<value_type> ilist)
1691 {
1692  return insert(pos, ilist.begin(), ilist.end());
1693 }
1694 
1722 template <typename T>
1723 template <class... Args>
1724 typename vector<T>::iterator
1725 vector<T>::emplace(const_iterator pos, Args &&... args)
1726 {
1727  pool_base pb = get_pool();
1728 
1729  size_type idx = static_cast<size_type>(std::distance(cbegin(), pos));
1730 
1731  transaction::run(pb, [&] {
1732  /*
1733  * args might be a reference to underlying array element. This
1734  * reference can be invalidated after internal_insert() call.
1735  * Hence, we must cache value_type object in temp_value.
1736  */
1737  detail::temp_value<value_type,
1738  noexcept(T(std::forward<Args>(args)...))>
1739  tmp(std::forward<Args>(args)...);
1740 
1741  auto &tmp_ref = tmp.get();
1742 
1743  internal_insert(idx, std::make_move_iterator(&tmp_ref),
1744  std::make_move_iterator(&tmp_ref + 1));
1745  });
1746 
1747  return iterator(&_data[static_cast<difference_type>(idx)]);
1748 }
1749 
1772 template <typename T>
1773 template <class... Args>
1774 typename vector<T>::reference
1775 vector<T>::emplace_back(Args &&... args)
1776 {
1777  /*
1778  * emplace() cannot be used here, because emplace_back() doesn't require
1779  * element_type to be MoveAssignable and emplace() uses
1780  * std::move_backward() function.
1781  */
1782  pool_base pb = get_pool();
1783 
1784  transaction::run(pb, [&] {
1785  if (_size == _capacity) {
1786  realloc(get_recommended_capacity(_size + 1));
1787  } else {
1788  add_data_to_tx(size(), 1);
1789  }
1790 
1791  construct_at_end(1, std::forward<Args>(args)...);
1792  });
1793 
1794  return back();
1795 }
1796 
1816 template <typename T>
1817 typename vector<T>::iterator
1818 vector<T>::erase(const_iterator pos)
1819 {
1820  return erase(pos, pos + 1);
1821 }
1822 
1845 template <typename T>
1846 typename vector<T>::iterator
1847 vector<T>::erase(const_iterator first, const_iterator last)
1848 {
1849  size_type idx = static_cast<size_type>(
1850  std::distance(const_iterator(_data.get()), first));
1851  size_type count = static_cast<size_type>(std::distance(first, last));
1852 
1853  if (count == 0)
1854  return iterator(&_data[static_cast<difference_type>(idx)]);
1855 
1856  pool_base pb = get_pool();
1857 
1858  transaction::run(pb, [&] {
1859  /*
1860  * XXX: future optimization: no need to snapshot trivial types,
1861  * if idx + count = _size
1862  */
1863  add_data_to_tx(idx, _size - idx);
1864 
1865  pointer move_begin =
1866  &_data[static_cast<difference_type>(idx + count)];
1867  pointer move_end = &_data[static_cast<difference_type>(size())];
1868  pointer dest = &_data[static_cast<difference_type>(idx)];
1869 
1870  std::move(move_begin, move_end, dest);
1871 
1872  _size -= count;
1873  });
1874 
1875  return iterator(&_data[static_cast<difference_type>(idx)]);
1876 }
1877 
1893 template <typename T>
1894 void
1895 vector<T>::push_back(const value_type &value)
1896 {
1897  emplace_back(value);
1898 }
1899 
1916 template <typename T>
1917 void
1918 vector<T>::push_back(value_type &&value)
1919 {
1920  emplace_back(std::move(value));
1921 }
1922 
1933 template <typename T>
1934 void
1936 {
1937  if (empty())
1938  return;
1939 
1940  pool_base pb = get_pool();
1941  transaction::run(pb, [&] { shrink(size() - 1); });
1942 }
1943 
1960 template <typename T>
1961 void
1962 vector<T>::resize(size_type count)
1963 {
1964  pool_base pb = get_pool();
1965  transaction::run(pb, [&] {
1966  if (count <= _size)
1967  shrink(count);
1968  else {
1969  if (_capacity < count)
1970  realloc(count);
1971  construct_at_end(count - _size);
1972  }
1973  });
1974 }
1975 
1993 template <typename T>
1994 void
1995 vector<T>::resize(size_type count, const value_type &value)
1996 {
1997  if (_capacity == count)
1998  return;
1999 
2000  pool_base pb = get_pool();
2001  transaction::run(pb, [&] {
2002  if (count <= _size)
2003  shrink(count);
2004  else {
2005  if (_capacity < count)
2006  realloc(count);
2007  construct_at_end(count - _size, value);
2008  }
2009  });
2010 }
2011 
2015 template <typename T>
2016 void
2018 {
2019  pool_base pb = get_pool();
2020  transaction::run(pb, [&] {
2021  std::swap(this->_data, other._data);
2022  std::swap(this->_size, other._size);
2023  std::swap(this->_capacity, other._capacity);
2024  });
2025 }
2026 
2033 template <typename T>
2034 void
2035 vector<T>::for_each_ptr(for_each_ptr_function func)
2036 {
2037  func(_data);
2038 }
2039 
2057 template <typename T>
2058 void
2059 vector<T>::alloc(size_type capacity_new)
2060 {
2061  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2062  assert(_data == nullptr);
2063  assert(_size == 0);
2064 
2065  if (capacity_new > max_size())
2066  throw std::length_error("New capacity exceeds max size.");
2067 
2068  _capacity = capacity_new;
2069 
2070  if (capacity_new == 0)
2071  return;
2072 
2073  /*
2074  * We need to cache pmemobj_tx_alloc return value and only after that
2075  * assign it to _data, because when pmemobj_tx_alloc fails, it aborts
2076  * transaction.
2077  */
2078  persistent_ptr<T[]> res =
2079  pmemobj_tx_alloc(sizeof(value_type) * capacity_new,
2080  detail::type_num<value_type>());
2081 
2082  if (res == nullptr) {
2083  if (errno == ENOMEM)
2085  "Failed to allocate persistent memory object")
2086  .with_pmemobj_errormsg();
2087  else
2089  "Failed to allocate persistent memory object")
2090  .with_pmemobj_errormsg();
2091  }
2092 
2093  _data = res;
2094 }
2095 
2102 template <typename T>
2103 void
2105 {
2106  if (nullptr == pmemobj_pool_by_ptr(this))
2107  throw pmem::pool_error("Invalid pool handle.");
2108 }
2109 
2117 template <typename T>
2118 void
2120 {
2121  if (pmemobj_tx_stage() != TX_STAGE_WORK)
2123  "Function called out of transaction scope.");
2124 }
2125 
2144 template <typename T>
2145 template <typename... Args>
2146 void
2147 vector<T>::construct_at_end(size_type count, Args &&... args)
2148 {
2149  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2150  assert(_capacity >= count + _size);
2151 
2152  pointer dest = _data.get() + size();
2153  const_pointer end = dest + count;
2154  for (; dest != end; ++dest)
2155  detail::create<value_type, Args...>(
2156  dest, std::forward<Args>(args)...);
2157  _size += count;
2158 }
2159 
2182 template <typename T>
2183 template <typename InputIt,
2184  typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2185  InputIt>::type *>
2186 void
2187 vector<T>::construct_at_end(InputIt first, InputIt last)
2188 {
2189  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2190  difference_type range_size = std::distance(first, last);
2191  assert(range_size >= 0);
2192  assert(_capacity >= static_cast<size_type>(range_size) + _size);
2193 
2194  pointer dest = _data.get() + size();
2195  _size += static_cast<size_type>(range_size);
2196  while (first != last)
2197  detail::create<value_type>(dest++, *first++);
2198 }
2199 
2215 template <typename T>
2216 void
2218 {
2219  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2220 
2221  if (_data != nullptr) {
2222  shrink(0);
2223  if (pmemobj_tx_free(*_data.raw_ptr()) != 0)
2225  "failed to delete persistent memory object")
2226  .with_pmemobj_errormsg();
2227  _data = nullptr;
2228  _capacity = 0;
2229  }
2230 }
2231 
2239 template <typename T>
2240 pool_base
2241 vector<T>::get_pool() const noexcept
2242 {
2243  auto pop = pmemobj_pool_by_ptr(this);
2244  assert(pop != nullptr);
2245  return pool_base(pop);
2246 }
2247 
2255 template <typename T>
2256 void
2257 vector<T>::move_elements_backward(pointer first, pointer last, pointer d_last)
2258 {
2259  while (first != last && d_last >= cend())
2260  detail::create<value_type>(--d_last, std::move(*(--last)));
2261 
2262  if (first != last)
2263  std::move_backward(first, last, d_last);
2264 }
2265 
2273 template <typename T>
2274 template <typename InputIt>
2275 void
2276 vector<T>::construct_or_assign(size_type idx, InputIt first, InputIt last)
2277 {
2278  auto count = static_cast<size_type>(std::distance(first, last));
2279  auto dest = _data.get() + idx;
2280  auto initialized_slots = static_cast<size_type>(cend() - dest);
2281 
2282  /* Assign new elements to initialized memory */
2283  if (dest < cend())
2284  dest = std::copy_n(first, (std::min)(initialized_slots, count),
2285  dest);
2286 
2287  std::advance(first, (std::min)(initialized_slots, count));
2288 
2289  /* Rest of the elements will be created in uninitialized memory */
2290  while (first != last)
2291  detail::create<value_type>(dest++, *first++);
2292 
2293  _size += count;
2294 }
2295 
2316 template <typename T>
2317 template <typename InputIt>
2318 void
2319 vector<T>::internal_insert(size_type idx, InputIt first, InputIt last)
2320 {
2321  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2322 
2323  auto count = static_cast<size_type>(std::distance(first, last));
2324 
2325  if (_capacity >= size() + count) {
2326  pointer dest = _data.get() +
2327  static_cast<difference_type>(size() + count);
2328  pointer begin = _data.get() + static_cast<difference_type>(idx);
2329  pointer end =
2330  _data.get() + static_cast<difference_type>(size());
2331 
2332  add_data_to_tx(idx, size() - idx + count);
2333 
2334  /* Make a gap for new elements */
2335  move_elements_backward(begin, end, dest);
2336 
2337  /* Construct new elements in the gap */
2338  construct_or_assign(idx, first, last);
2339  } else {
2340  /*
2341  * XXX: future optimization: we don't have to snapshot data
2342  * which we will copy (only snapshot for move)
2343  */
2344  add_data_to_tx(0, _size);
2345 
2346  auto old_data = _data;
2347  auto old_size = _size;
2348  pointer old_begin = _data.get();
2349  pointer old_mid =
2350  _data.get() + static_cast<difference_type>(idx);
2351  pointer old_end =
2352  _data.get() + static_cast<difference_type>(size());
2353 
2354  _data = nullptr;
2355  _size = _capacity = 0;
2356 
2357  alloc(get_recommended_capacity(old_size + count));
2358 
2359  /* Move range before the idx to new array */
2360  construct_at_end(std::make_move_iterator(old_begin),
2361  std::make_move_iterator(old_mid));
2362 
2363  /* Insert (first, last) range to the new array */
2364  construct_at_end(first, last);
2365 
2366  /* Move remaining element to the new array */
2367  construct_at_end(std::make_move_iterator(old_mid),
2368  std::make_move_iterator(old_end));
2369 
2370  /* destroy and free old data */
2371  for (size_type i = 0; i < old_size; ++i)
2372  detail::destroy<value_type>(
2373  old_data[static_cast<difference_type>(i)]);
2374  if (pmemobj_tx_free(old_data.raw()) != 0)
2376  "failed to delete persistent memory object")
2377  .with_pmemobj_errormsg();
2378  }
2379 }
2380 
2399 template <typename T>
2400 void
2401 vector<T>::realloc(size_type capacity_new)
2402 {
2403  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2404 
2405  /*
2406  * If _data == nullptr this object has never allocated any memory
2407  * so we need to behave as alloc instead.
2408  */
2409  if (_data == nullptr)
2410  return alloc(capacity_new);
2411 
2412  /*
2413  * XXX: future optimization: we don't have to snapshot data
2414  * which we will not overwrite
2415  */
2416  add_data_to_tx(0, _size);
2417 
2418  auto old_data = _data;
2419  auto old_size = _size;
2420  pointer old_begin = _data.get();
2421  pointer old_end = capacity_new < _size
2422  ? &_data[static_cast<difference_type>(capacity_new)]
2423  : &_data[static_cast<difference_type>(size())];
2424 
2425  _data = nullptr;
2426  _size = _capacity = 0;
2427 
2428  alloc(capacity_new);
2429 
2430  construct_at_end(std::make_move_iterator(old_begin),
2431  std::make_move_iterator(old_end));
2432 
2433  /* destroy and free old data */
2434  for (size_type i = 0; i < old_size; ++i)
2435  detail::destroy<value_type>(
2436  old_data[static_cast<difference_type>(i)]);
2437  if (pmemobj_tx_free(old_data.raw()) != 0)
2439  "failed to delete persistent memory object")
2440  .with_pmemobj_errormsg();
2441 }
2442 
2449 template <typename T>
2450 typename vector<T>::size_type
2451 vector<T>::get_recommended_capacity(size_type at_least) const
2452 {
2453  return detail::next_pow_2(at_least);
2454 }
2455 
2472 template <typename T>
2473 void
2474 vector<T>::shrink(size_type size_new)
2475 {
2476  assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2477  assert(size_new <= _size);
2478 
2479  add_data_to_tx(size_new, _size - size_new);
2480 
2481  for (size_type i = size_new; i < _size; ++i)
2482  detail::destroy<value_type>(
2483  _data[static_cast<difference_type>(i)]);
2484  _size = size_new;
2485 }
2486 
2496 template <typename T>
2497 void
2498 vector<T>::add_data_to_tx(size_type idx_first, size_type num)
2499 {
2500  assert(idx_first + num <= capacity());
2501 
2502 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2503  /* Make sure that only data allocated by this vector is accessed */
2504  assert(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_data.get() + idx_first,
2505  num * sizeof(T)) == 0);
2506 #endif
2507 
2508  auto initialized_num = size() - idx_first;
2509 
2510  /* Snapshot elements in range [idx_first,size()) */
2511  detail::conditional_add_to_tx(_data.get() + idx_first,
2512  (std::min)(initialized_num, num),
2513  POBJ_XADD_ASSUME_INITIALIZED);
2514 
2515  if (num > initialized_num) {
2516  /* Elements after size() do not have to be snapshotted */
2517  detail::conditional_add_to_tx(_data.get() + size(),
2518  num - initialized_num,
2519  POBJ_XADD_NO_SNAPSHOT);
2520  }
2521 }
2522 
2534 template <typename T>
2535 bool
2536 operator==(const vector<T> &lhs, const vector<T> &rhs)
2537 {
2538  return lhs.size() == rhs.size() &&
2539  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2540 }
2541 
2553 template <typename T>
2554 bool
2555 operator!=(const vector<T> &lhs, const vector<T> &rhs)
2556 {
2557  return !(lhs == rhs);
2558 }
2559 
2570 template <typename T>
2571 bool
2572 operator<(const vector<T> &lhs, const vector<T> &rhs)
2573 {
2574  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2575  rhs.end());
2576 }
2577 
2588 template <typename T>
2589 bool
2590 operator<=(const vector<T> &lhs, const vector<T> &rhs)
2591 {
2592  return !(rhs < lhs);
2593 }
2594 
2606 template <typename T>
2607 bool
2608 operator>(const vector<T> &lhs, const vector<T> &rhs)
2609 {
2610  return rhs < lhs;
2611 }
2612 
2623 template <typename T>
2624 bool
2625 operator>=(const vector<T> &lhs, const vector<T> &rhs)
2626 {
2627  return !(lhs < rhs);
2628 }
2629 
2641 template <typename T>
2642 bool
2643 operator==(const vector<T> &lhs, const std::vector<T> &rhs)
2644 {
2645  return lhs.size() == rhs.size() &&
2646  std::equal(lhs.begin(), lhs.end(), rhs.begin());
2647 }
2648 
2660 template <typename T>
2661 bool
2662 operator!=(const vector<T> &lhs, const std::vector<T> &rhs)
2663 {
2664  return !(lhs == rhs);
2665 }
2666 
2677 template <typename T>
2678 bool
2679 operator<(const vector<T> &lhs, const std::vector<T> &rhs)
2680 {
2681  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
2682  rhs.end());
2683 }
2684 
2695 template <typename T>
2696 bool
2697 operator<=(const vector<T> &lhs, const std::vector<T> &rhs)
2698 {
2699  return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2700  lhs.begin(), lhs.end()));
2701 }
2702 
2714 template <typename T>
2715 bool
2716 operator>(const vector<T> &lhs, const std::vector<T> &rhs)
2717 {
2718  return !(lhs <= rhs);
2719 }
2720 
2731 template <typename T>
2732 bool
2733 operator>=(const vector<T> &lhs, const std::vector<T> &rhs)
2734 {
2735  return !(lhs < rhs);
2736 }
2737 
2749 template <typename T>
2750 bool
2751 operator==(const std::vector<T> &lhs, const vector<T> &rhs)
2752 {
2753  return rhs == lhs;
2754 }
2755 
2767 template <typename T>
2768 bool
2769 operator!=(const std::vector<T> &lhs, const vector<T> &rhs)
2770 {
2771  return !(lhs == rhs);
2772 }
2773 
2784 template <typename T>
2785 bool
2786 operator<(const std::vector<T> &lhs, const vector<T> &rhs)
2787 {
2788  return rhs > lhs;
2789 }
2790 
2801 template <typename T>
2802 bool
2803 operator<=(const std::vector<T> &lhs, const vector<T> &rhs)
2804 {
2805  return !(rhs < lhs);
2806 }
2807 
2819 template <typename T>
2820 bool
2821 operator>(const std::vector<T> &lhs, const vector<T> &rhs)
2822 {
2823  return rhs < lhs;
2824 }
2825 
2836 template <typename T>
2837 bool
2838 operator>=(const std::vector<T> &lhs, const vector<T> &rhs)
2839 {
2840  return !(lhs < rhs);
2841 }
2842 
2849 template <typename T>
2850 void
2852 {
2853  lhs.swap(rhs);
2854 }
2855 
2856 } /* namespace obj */
2857 
2858 } /* namespace pmem */
2859 
2860 #endif /* LIBPMEMOBJ_CPP_VECTOR_HPP */
pmem::obj::vector::erase
iterator erase(const_iterator pos)
Removes the element at pos.
Definition: vector.hpp:1818
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:1020
pmem::obj::vector::construct_at_end
void construct_at_end(InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2187
pmem::obj::vector::vector
vector(const vector &other)
Copy constructor.
Definition: vector.hpp:473
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:212
pmem::obj::vector::dealloc
void dealloc()
Private helper function.
Definition: vector.hpp:2217
pmem::obj::vector::vector
vector(std::initializer_list< T > init)
Constructs the container with the contents of the initializer list init.
Definition: vector.hpp:534
pmem::obj::vector::crend
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: vector.hpp:1249
pmem::obj::vector::realloc
void realloc(size_type size)
Private helper function.
Definition: vector.hpp:2401
pmem::obj::vector::data
value_type * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: vector.hpp:1066
pmem::obj::vector::const_at
const_reference const_at(size_type n) const
Access element at specific index with bounds checking.
Definition: vector.hpp:925
pmem::obj::vector::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: vector.hpp:1208
pmem::transaction_free_error
Custom transaction error class.
Definition: pexceptions.hpp:169
pmem::obj::vector::clear
void clear()
Clears the content of a vector transactionally.
Definition: vector.hpp:1465
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:74
pmem::obj::vector::operator[]
const_reference operator[](size_type n) const
Access element at specific index.
Definition: vector.hpp:961
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:44
pmem::transaction_out_of_memory
Custom out of memory error class.
Definition: pexceptions.hpp:149
pmem::obj::vector::~vector
~vector()
Destructor.
Definition: vector.hpp:862
pmem::obj::vector::shrink_to_fit
void shrink_to_fit()
Requests transactional removal of unused capacity.
Definition: vector.hpp:1445
pmem::obj::begin
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:833
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:763
pmem::obj::vector::crange
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: vector.hpp:1348
pmem::obj::vector::end
iterator end()
Returns an iterator to past the end.
Definition: vector.hpp:1144
pmem::obj::vector::swap
void swap(vector &other)
Exchanges the contents of the container with other transactionally.
Definition: vector.hpp:2017
pmem::obj::vector::cfront
const_reference cfront() const
Access the first element.
Definition: vector.hpp:1005
pmem::obj::operator++
p< T > & operator++(p< T > &pp)
Prefix increment operator overload.
Definition: pext.hpp:77
pmem::obj::vector::alloc
void alloc(size_type size)
Private helper function.
Definition: vector.hpp:2059
pmem::obj::operator>=
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:773
pmem::obj::vector::assign
void assign(const std::vector< T > &other)
Copy assignment method.
Definition: vector.hpp:847
pmem::obj::vector::check_pmem
void check_pmem()
Private helper function.
Definition: vector.hpp:2104
pmem::obj::vector::get_pool
pool_base get_pool() const noexcept
Private helper function.
Definition: vector.hpp:2241
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:402
pmem::obj::vector::vector
vector(vector &&other)
Move constructor.
Definition: vector.hpp:504
pmem::obj::p
Resides on pmem class.
Definition: p.hpp:64
pmem::obj::vector::operator=
vector & operator=(const vector &other)
Copy assignment operator.
Definition: vector.hpp:576
pmem::obj::vector::vector
vector(InputIt first, InputIt last)
Constructs the container with the contents of the range [first, last).
Definition: vector.hpp:443
pmem::obj::vector::construct_or_assign
void construct_or_assign(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2276
pmem::obj::vector::size
size_type size() const noexcept
Definition: vector.hpp:1374
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:1106
pmem::obj::vector::construct_at_end
void construct_at_end(size_type count, Args &&... args)
Private helper function.
Definition: vector.hpp:2147
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:422
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:882
pmem::obj::swap
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:913
pmem::obj::vector::rend
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: vector.hpp:1221
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:2035
pmem::obj::vector::assign
void assign(const vector &other)
Copy assignment method.
Definition: vector.hpp:795
pmem::detail::basic_contiguous_iterator
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:360
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:518
pmem::obj::cend
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:803
pmem::obj::swap
void swap(vector< T > &lhs, vector< T > &rhs)
Swaps the contents of lhs and rhs.
Definition: vector.hpp:2851
pmem::obj::vector::vector
vector(const std::vector< T > &other)
Copy constructor.
Definition: vector.hpp:558
pmem::obj::vector::reserve
void reserve(size_type capacity_new)
Increases the capacity of the vector to capacity_new transactionally.
Definition: vector.hpp:1410
pmem::obj::vector::back
const_reference back() const
Access the last element.
Definition: vector.hpp:1036
pmem::obj::vector::empty
constexpr bool empty() const noexcept
Checks whether the container is empty.
Definition: vector.hpp:1364
pmem::obj::vector
pmem::obj::vector - persistent container with std::vector compatible interface.
Definition: vector.hpp:69
pmem::obj::vector::cback
const_reference cback() const
Access the last element.
Definition: vector.hpp:1050
pmem::obj::vector::data
const value_type * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: vector.hpp:1080
pmem::obj::vector::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: vector.hpp:1132
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:595
pmem::obj::vector::at
const_reference at(size_type n) const
Access element at specific index with bounds checking.
Definition: vector.hpp:903
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:1485
pmem::detail::is_input_iterator
Type trait to determine if a given parameter type satisfies requirements of InputIterator.
Definition: iterator_traits.hpp:76
pmem::detail::temp_value
Template class for caching objects based on constructor's variadic template arguments and LIBPMEMOBJ_...
Definition: temp_value.hpp:64
pmem::obj::vector::vector
vector()
Default constructor.
Definition: vector.hpp:348
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:1895
pmem::obj::vector::front
reference front()
Access the first element and add this element to a transaction.
Definition: vector.hpp:976
temp_value.hpp
temp_value template class for caching objects.
pmem::obj::persistent_ptr
Persistent pointer class.
Definition: persistent_ptr.hpp:212
pmem::obj::end
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:853
pmem::obj::vector::emplace_back
reference emplace_back(Args &&... args)
Appends a new element to the end of the container.
Definition: vector.hpp:1775
pmem::obj::vector::max_size
constexpr size_type max_size() const noexcept
Definition: vector.hpp:1385
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:752
pmem::obj::vector::emplace
iterator emplace(const_iterator pos, Args &&... args)
Inserts a new element into the container directly before pos.
Definition: vector.hpp:1725
pmem::obj::vector::operator=
vector & operator=(const std::vector< T > &other)
Copy assignment operator.
Definition: vector.hpp:634
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:777
pmem::obj::cbegin
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:793
pmem::obj::vector::vector
vector(size_type count)
Constructs the container with count copies of T default constructed values.
Definition: vector.hpp:406
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:2498
pmem::obj::vector::range
slice< pointer > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: vector.hpp:1269
pmem::obj::slice
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:56
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:717
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:783
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:221
life.hpp
Functions for destroying arrays.
pmem::obj::vector::rbegin
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: vector.hpp:1182
pmem::obj::vector::shrink
void shrink(size_type size_new)
Private helper function.
Definition: vector.hpp:2474
pmem::obj::vector::resize
void resize(size_type count)
Resizes the container to count elements transactionally.
Definition: vector.hpp:1962
pmem::obj::persistent_ptr_base
Persistent_ptr base (non-template) class.
Definition: persistent_ptr_base.hpp:71
pmem::transaction_scope_error
Custom transaction error class.
Definition: pexceptions.hpp:187
pmem::obj::vector::move_elements_backward
void move_elements_backward(pointer first, pointer last, pointer d_last)
Private helper function.
Definition: vector.hpp:2257
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:881
pmem::obj::vector::operator[]
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: vector.hpp:945
pmem::obj::vector::pop_back
void pop_back()
Removes the last element of the container transactionally.
Definition: vector.hpp:1935
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:613
pmem::obj::vector::get_recommended_capacity
size_type get_recommended_capacity(size_type at_least) const
Private helper function.
Definition: vector.hpp:2451
pmem::obj::vector::front
const_reference front() const
Access the first element.
Definition: vector.hpp:991
pmem::obj::pool_base
The non-template pool base class.
Definition: pool.hpp:75
pmem::obj::vector::capacity
size_type capacity() const noexcept
Definition: vector.hpp:1424
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:377
pmem::obj::vector::cend
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: vector.hpp:1170
pmem::obj::vector::check_tx_stage_work
void check_tx_stage_work()
Private helper function.
Definition: vector.hpp:2119
pmem::obj::vector::insert
iterator insert(const_iterator pos, const T &value)
Inserts value before pos in the container transactionally.
Definition: vector.hpp:1520
pmem::transaction_alloc_error
Custom transaction error class.
Definition: pexceptions.hpp:130
pmem::obj::vector::cdata
const value_type * cdata() const noexcept
Returns const raw pointer to the underlying data.
Definition: vector.hpp:1094
pmem::obj::vector::internal_insert
void internal_insert(size_type idx, InputIt first, InputIt last)
Private helper function.
Definition: vector.hpp:2319
pmem::obj::vector::assign
void assign(vector &&other)
Move assignment method.
Definition: vector.hpp:814