9 #ifndef LIBPMEMOBJ_CPP_VECTOR_HPP
10 #define LIBPMEMOBJ_CPP_VECTOR_HPP
16 #include <libpmemobj++/detail/temp_value.hpp>
23 #include <libpmemobj/base.h>
45 using size_type = std::size_t;
46 using difference_type = std::ptrdiff_t;
47 using reference = value_type &;
48 using const_reference =
const value_type &;
49 using pointer = value_type *;
50 using const_pointer =
const value_type *;
52 using const_iterator = const_pointer;
53 using reverse_iterator = std::reverse_iterator<iterator>;
54 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
58 using for_each_ptr_function =
63 vector(size_type count,
const value_type &value);
65 template <
typename InputIt,
66 typename std::enable_if<
68 InputIt>::type * =
nullptr>
72 vector(std::initializer_list<T> init);
82 void assign(size_type count,
const T &value);
83 template <
typename InputIt,
84 typename std::enable_if<
86 InputIt>::type * =
nullptr>
87 void assign(InputIt first, InputIt last);
88 void assign(std::initializer_list<T> ilist);
91 void assign(
const std::vector<T> &other);
97 reference
at(size_type n);
98 const_reference
at(size_type n)
const;
109 const value_type *
data() const noexcept;
110 const value_type *
cdata() const noexcept;
114 const_iterator
begin() const noexcept;
117 const_iterator
end() const noexcept;
118 const_iterator
cend() const noexcept;
120 const_reverse_iterator
rbegin() const noexcept;
121 const_reverse_iterator
crbegin() const noexcept;
123 const_reverse_iterator
rend() const noexcept;
124 const_reverse_iterator
crend() const noexcept;
129 size_type snapshot_size);
130 slice<const_iterator>
range(size_type start, size_type n) const;
135 constexpr
bool empty() const noexcept;
136 size_type
size() const noexcept;
148 template <typename InputIt,
149 typename std::enable_if<
150 detail::is_input_iterator<InputIt>::value,
151 InputIt>::type * =
nullptr>
154 template <class... Args>
156 template <class... Args>
164 void resize(size_type count, const value_type &value);
169 template <typename P>
170 struct single_element_iterator {
171 using iterator_category = std::input_iterator_tag;
172 using value_type = P;
173 using difference_type = std::ptrdiff_t;
174 using pointer =
const P *;
175 using reference =
const P &;
180 single_element_iterator(
const P *ptr, std::size_t count = 0)
181 : ptr(ptr), count(count)
185 reference operator*()
195 single_element_iterator &
202 single_element_iterator
205 single_element_iterator tmp =
206 single_element_iterator(ptr, count);
212 operator-(
const single_element_iterator &rhs)
214 return count - rhs.count;
218 operator!=(
const single_element_iterator &rhs)
220 return ptr != rhs.ptr || count != rhs.count;
228 template <
typename... Args>
230 template <
typename InputIt,
231 typename std::enable_if<
233 InputIt>::type * =
nullptr>
237 template <
typename InputIt>
243 template <
typename InputIt>
256 template <
typename T>
263 template <
typename T>
265 template <
typename T>
267 template <
typename T>
269 template <
typename T>
271 template <
typename T>
273 template <
typename T>
280 template <
typename T>
282 template <
typename T>
284 template <
typename T>
286 template <
typename T>
288 template <
typename T>
290 template <
typename T>
297 template <
typename T>
299 template <
typename T>
301 template <
typename T>
303 template <
typename T>
305 template <
typename T>
307 template <
typename T>
319 template <
typename T>
323 check_tx_stage_work();
348 template <
typename T>
352 check_tx_stage_work();
357 construct_at_end(count, value);
377 template <
typename T>
381 check_tx_stage_work();
386 construct_at_end(count);
411 template <
typename T>
412 template <
typename InputIt,
413 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
418 check_tx_stage_work();
422 alloc(
static_cast<size_type
>(std::distance(first, last)));
423 construct_at_end(first, last);
444 template <
typename T>
448 check_tx_stage_work();
453 construct_at_end(other.
cbegin(), other.
cend());
475 template <
typename T>
479 check_tx_stage_work();
482 _capacity = other.capacity();
483 _size = other.size();
484 other._data =
nullptr;
485 other._capacity = other._size = 0;
505 template <
typename T>
529 template <
typename T>
546 template <
typename T>
565 template <
typename T>
569 assign(std::move(other));
583 template <
typename T>
587 assign(ilist.begin(), ilist.end());
604 template <
typename T>
629 template <
typename T>
636 if (count <= capacity()) {
643 size_type size_old = _size;
644 add_data_to_tx(0, size_old);
649 static_cast<size_type
>(size_old)),
652 if (count > size_old) {
653 add_data_to_tx(size_old, count - size_old);
654 construct_at_end(count - size_old, value);
661 construct_at_end(count, value);
684 template <
typename T>
685 template <
typename InputIt,
686 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
693 size_type size_new =
static_cast<size_type
>(std::distance(first, last));
696 if (size_new <= capacity()) {
703 size_type size_old = _size;
704 add_data_to_tx(0, size_old);
707 bool growing = size_new > size_old;
710 add_data_to_tx(size_old, size_new - size_old);
713 std::advance(mid, size_old);
716 iterator shrink_to = std::copy(first, mid, &_data[0]);
719 construct_at_end(mid, last);
721 shrink(
static_cast<size_type
>(std::distance(
727 construct_at_end(first, last);
747 template <
typename T>
751 assign(ilist.begin(), ilist.end());
765 template <
typename T>
784 template <
typename T>
797 _capacity = other._capacity;
800 other._data =
nullptr;
801 other._capacity = other._size = 0;
817 template <
typename T>
821 assign(other.cbegin(), other.cend());
831 template <
typename T>
853 template <
typename T>
854 typename vector<T>::reference
858 throw std::out_of_range(
"vector::at");
860 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)],
861 1, POBJ_XADD_ASSUME_INITIALIZED);
863 return _data[
static_cast<difference_type
>(n)];
875 template <
typename T>
876 typename vector<T>::const_reference
880 throw std::out_of_range(
"vector::at");
882 return _data[
static_cast<difference_type
>(n)];
897 template <
typename T>
898 typename vector<T>::const_reference
902 throw std::out_of_range(
"vector::const_at");
904 return _data[
static_cast<difference_type
>(n)];
918 template <
typename T>
921 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)],
922 1, POBJ_XADD_ASSUME_INITIALIZED);
924 return _data[
static_cast<difference_type
>(n)];
934 template <
typename T>
937 return _data[
static_cast<difference_type
>(n)];
948 template <
typename T>
949 typename vector<T>::reference
952 detail::conditional_add_to_tx(&_data[0], 1,
953 POBJ_XADD_ASSUME_INITIALIZED);
963 template <
typename T>
964 typename vector<T>::const_reference
977 template <
typename T>
978 typename vector<T>::const_reference
992 template <
typename T>
993 typename vector<T>::reference
996 detail::conditional_add_to_tx(
997 &_data[
static_cast<difference_type
>(size() - 1)], 1,
998 POBJ_XADD_ASSUME_INITIALIZED);
1000 return _data[
static_cast<difference_type
>(size() - 1)];
1008 template <
typename T>
1009 typename vector<T>::const_reference
1012 return _data[
static_cast<difference_type
>(size() - 1)];
1022 template <
typename T>
1023 typename vector<T>::const_reference
1026 return _data[
static_cast<difference_type
>(size() - 1)];
1038 template <
typename T>
1039 typename vector<T>::value_type *
1042 add_data_to_tx(0, _size);
1052 template <
typename T>
1053 const typename vector<T>::value_type *
1066 template <
typename T>
1067 const typename vector<T>::value_type *
1078 template <
typename T>
1090 template <
typename T>
1091 typename vector<T>::const_iterator
1094 return const_iterator(_data.get());
1104 template <
typename T>
1105 typename vector<T>::const_iterator
1108 return const_iterator(_data.get());
1116 template <
typename T>
1120 return iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1128 template <
typename T>
1129 typename vector<T>::const_iterator
1132 return const_iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1142 template <
typename T>
1143 typename vector<T>::const_iterator
1146 return const_iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1154 template <
typename T>
1155 typename vector<T>::reverse_iterator
1158 return reverse_iterator(
end());
1166 template <
typename T>
1167 typename vector<T>::const_reverse_iterator
1170 return const_reverse_iterator(
cend());
1180 template <
typename T>
1181 typename vector<T>::const_reverse_iterator
1184 return const_reverse_iterator(
cend());
1193 template <
typename T>
1194 typename vector<T>::reverse_iterator
1197 return reverse_iterator(
begin());
1206 template <
typename T>
1207 typename vector<T>::const_reverse_iterator
1210 return const_reverse_iterator(
cbegin());
1221 template <
typename T>
1222 typename vector<T>::const_reverse_iterator
1225 return const_reverse_iterator(
cbegin());
1241 template <
typename T>
1245 if (start + n > size())
1246 throw std::out_of_range(
"vector::range");
1248 detail::conditional_add_to_tx(cdata() + start, n,
1249 POBJ_XADD_ASSUME_INITIALIZED);
1251 return {_data.get() + start, _data.get() + start + n};
1269 template <
typename T>
1273 if (start + n > size())
1274 throw std::out_of_range(
"vector::range");
1276 if (snapshot_size > n)
1280 _data.get() + start, n,
1283 _data.get() + start, n,
1298 template <
typename T>
1302 if (start + n > size())
1303 throw std::out_of_range(
"vector::range");
1305 return {const_iterator(cdata() + start),
1306 const_iterator(cdata() + start + n)};
1320 template <
typename T>
1324 if (start + n > size())
1325 throw std::out_of_range(
"vector::crange");
1327 return {const_iterator(cdata() + start),
1328 const_iterator(cdata() + start + n)};
1336 template <
typename T>
1346 template <
typename T>
1347 typename vector<T>::size_type
1357 template <
typename T>
1358 constexpr
typename vector<T>::size_type
1361 return PMEMOBJ_MAX_ALLOC_SIZE /
sizeof(value_type);
1382 template <
typename T>
1386 if (capacity_new <= _capacity)
1396 template <
typename T>
1397 typename vector<T>::size_type
1417 template <
typename T>
1421 size_type capacity_new = size();
1422 if (capacity() == capacity_new)
1437 template <
typename T>
1457 template <
typename T>
1461 if (_data ==
nullptr)
1492 template <
typename T>
1496 return insert(pos, 1, value);
1523 template <
typename T>
1529 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1532 internal_insert(idx, std::make_move_iterator(&value),
1533 std::make_move_iterator(&value + 1));
1536 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1567 template <
typename T>
1573 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1577 idx, single_element_iterator<value_type>(&value, 0),
1578 single_element_iterator<value_type>(&value, count));
1581 return iterator(_data.get() +
static_cast<difference_type
>(idx));
1618 template <
typename T>
1619 template <
typename InputIt,
1620 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1627 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1631 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1662 template <
typename T>
1666 return insert(pos, ilist.begin(), ilist.end());
1696 template <
typename T>
1697 template <
class... Args>
1703 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1711 detail::temp_value<value_type,
1712 noexcept(T(std::forward<Args>(args)...))>
1713 tmp(std::forward<Args>(args)...);
1715 auto &tmp_ref = tmp.get();
1717 internal_insert(idx, std::make_move_iterator(&tmp_ref),
1718 std::make_move_iterator(&tmp_ref + 1));
1721 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1746 template <
typename T>
1747 template <
class... Args>
1748 typename vector<T>::reference
1759 if (_size == _capacity) {
1760 realloc(get_recommended_capacity(_size + 1));
1762 add_data_to_tx(size(), 1);
1765 construct_at_end(1, std::forward<Args>(args)...);
1790 template <
typename T>
1794 return erase(pos, pos + 1);
1819 template <
typename T>
1823 size_type idx =
static_cast<size_type
>(
1824 std::distance(const_iterator(_data.get()), first));
1825 size_type count =
static_cast<size_type
>(std::distance(first, last));
1828 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1833 if (!std::is_trivially_destructible<T>::value ||
1834 idx + count < _size)
1835 add_data_to_tx(idx, _size - idx);
1837 pointer move_begin =
1838 &_data[
static_cast<difference_type
>(idx + count)];
1839 pointer move_end = &_data[
static_cast<difference_type
>(size())];
1840 pointer dest = &_data[
static_cast<difference_type
>(idx)];
1842 std::move(move_begin, move_end, dest);
1847 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1865 template <
typename T>
1869 emplace_back(value);
1888 template <
typename T>
1892 emplace_back(std::move(value));
1905 template <
typename T>
1932 template <
typename T>
1941 if (_capacity < count)
1943 construct_at_end(count - _size);
1965 template <
typename T>
1969 if (_capacity == count)
1977 if (_capacity < count)
1979 construct_at_end(count - _size, value);
1987 template <
typename T>
1995 std::swap(this->_capacity, other._capacity);
2005 template <
typename T>
2029 template <
typename T>
2033 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2034 assert(_data ==
nullptr);
2037 if (capacity_new > max_size())
2038 throw std::length_error(
"New capacity exceeds max size.");
2040 _capacity = capacity_new;
2042 if (capacity_new == 0)
2051 pmemobj_tx_alloc(
sizeof(value_type) * capacity_new,
2052 detail::type_num<value_type>());
2054 if (res ==
nullptr) {
2055 if (errno == ENOMEM)
2057 "Failed to allocate persistent memory object")
2058 .with_pmemobj_errormsg();
2061 "Failed to allocate persistent memory object")
2062 .with_pmemobj_errormsg();
2074 template <
typename T>
2078 if (
nullptr == pmemobj_pool_by_ptr(
this))
2089 template <
typename T>
2093 if (pmemobj_tx_stage() != TX_STAGE_WORK)
2095 "Function called out of transaction scope.");
2116 template <
typename T>
2117 template <
typename... Args>
2121 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2122 assert(_capacity >= count + _size);
2124 pointer dest = _data.get() + size();
2125 const_pointer
end = dest + count;
2126 for (; dest !=
end; ++dest)
2127 detail::create<value_type, Args...>(
2128 dest, std::forward<Args>(args)...);
2154 template <
typename T>
2155 template <
typename InputIt,
2156 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2161 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2162 difference_type range_size = std::distance(first, last);
2163 assert(range_size >= 0);
2164 assert(_capacity >=
static_cast<size_type
>(range_size) + _size);
2166 pointer dest = _data.get() + size();
2167 _size +=
static_cast<size_type
>(range_size);
2168 while (first != last)
2169 detail::create<value_type>(dest++, *first++);
2187 template <
typename T>
2191 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2193 if (_data !=
nullptr) {
2195 if (pmemobj_tx_free(*_data.raw_ptr()) != 0)
2197 "failed to delete persistent memory object")
2198 .with_pmemobj_errormsg();
2211 template <
typename T>
2225 template <
typename T>
2229 while (first != last && d_last >=
cend())
2230 detail::create<value_type>(--d_last, std::move(*(--last)));
2233 std::move_backward(first, last, d_last);
2243 template <
typename T>
2244 template <
typename InputIt>
2248 auto count =
static_cast<size_type
>(std::distance(first, last));
2249 auto dest = _data.get() + idx;
2250 auto initialized_slots =
static_cast<size_type
>(
cend() - dest);
2254 dest = std::copy_n(first, (std::min)(initialized_slots, count),
2257 std::advance(first, (std::min)(initialized_slots, count));
2260 while (first != last)
2261 detail::create<value_type>(dest++, *first++);
2286 template <
typename T>
2287 template <
typename InputIt>
2291 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2293 auto count =
static_cast<size_type
>(std::distance(first, last));
2295 if (_capacity >= size() + count) {
2296 pointer dest = _data.get() +
2297 static_cast<difference_type
>(size() + count);
2298 pointer
begin = _data.get() +
static_cast<difference_type
>(idx);
2300 _data.get() +
static_cast<difference_type
>(size());
2302 add_data_to_tx(idx, size() - idx + count);
2305 move_elements_backward(
begin,
end, dest);
2308 construct_or_assign(idx, first, last);
2314 add_data_to_tx(0, _size);
2316 auto old_data = _data;
2317 auto old_size = _size;
2318 pointer old_begin = _data.get();
2320 _data.get() +
static_cast<difference_type
>(idx);
2322 _data.get() +
static_cast<difference_type
>(size());
2325 _size = _capacity = 0;
2327 alloc(get_recommended_capacity(old_size + count));
2330 construct_at_end(std::make_move_iterator(old_begin),
2331 std::make_move_iterator(old_mid));
2334 construct_at_end(first, last);
2337 construct_at_end(std::make_move_iterator(old_mid),
2338 std::make_move_iterator(old_end));
2341 for (size_type i = 0; i < old_size; ++i)
2342 detail::destroy<value_type>(
2343 old_data[
static_cast<difference_type
>(i)]);
2344 if (pmemobj_tx_free(old_data.raw()) != 0)
2346 "failed to delete persistent memory object")
2347 .with_pmemobj_errormsg();
2369 template <
typename T>
2373 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2379 if (_data ==
nullptr)
2380 return alloc(capacity_new);
2386 add_data_to_tx(0, _size);
2388 auto old_data = _data;
2389 auto old_size = _size;
2390 pointer old_begin = _data.get();
2391 pointer old_end = capacity_new < _size
2392 ? &_data[
static_cast<difference_type
>(capacity_new)]
2393 : &_data[
static_cast<difference_type
>(size())];
2396 _size = _capacity = 0;
2398 alloc(capacity_new);
2400 construct_at_end(std::make_move_iterator(old_begin),
2401 std::make_move_iterator(old_end));
2404 for (size_type i = 0; i < old_size; ++i)
2405 detail::destroy<value_type>(
2406 old_data[
static_cast<difference_type
>(i)]);
2407 if (pmemobj_tx_free(old_data.raw()) != 0)
2409 "failed to delete persistent memory object")
2410 .with_pmemobj_errormsg();
2419 template <
typename T>
2420 typename vector<T>::size_type
2442 template <
typename T>
2446 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2447 assert(size_new <= _size);
2449 if (!std::is_trivially_destructible<T>::value)
2450 add_data_to_tx(size_new, _size - size_new);
2452 for (size_type i = size_new; i < _size; ++i)
2453 detail::destroy<value_type>(
2454 _data[
static_cast<difference_type
>(i)]);
2467 template <
typename T>
2471 assert(idx_first + num <= capacity());
2473 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2475 assert(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_data.get() + idx_first,
2476 num *
sizeof(T)) == 0);
2479 auto initialized_num = size() - idx_first;
2482 detail::conditional_add_to_tx(_data.get() + idx_first,
2483 (std::min)(initialized_num, num),
2484 POBJ_XADD_ASSUME_INITIALIZED);
2486 if (num > initialized_num) {
2488 detail::conditional_add_to_tx(_data.get() + size(),
2489 num - initialized_num,
2490 POBJ_XADD_NO_SNAPSHOT);
2505 template <
typename T>
2524 template <
typename T>
2528 return !(lhs == rhs);
2541 template <
typename T>
2545 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2559 template <
typename T>
2563 return !(rhs < lhs);
2577 template <
typename T>
2594 template <
typename T>
2598 return !(lhs < rhs);
2612 template <
typename T>
2616 return lhs.
size() == rhs.size() &&
2617 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2631 template <
typename T>
2635 return !(lhs == rhs);
2648 template <
typename T>
2652 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2666 template <
typename T>
2670 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2685 template <
typename T>
2689 return !(lhs <= rhs);
2702 template <
typename T>
2706 return !(lhs < rhs);
2720 template <
typename T>
2738 template <
typename T>
2742 return !(lhs == rhs);
2755 template <
typename T>
2772 template <
typename T>
2776 return !(rhs < lhs);
2790 template <
typename T>
2807 template <
typename T>
2811 return !(lhs < rhs);
2820 template <
typename T>