38 #ifndef LIBPMEMOBJ_CPP_VECTOR_HPP
39 #define LIBPMEMOBJ_CPP_VECTOR_HPP
51 #include <libpmemobj/base.h>
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>;
88 vector(size_type count,
const value_type &value);
90 template <
typename InputIt,
91 typename std::enable_if<
93 InputIt>::type * =
nullptr>
97 vector(std::initializer_list<T> init);
107 void assign(size_type count,
const T &value);
108 template <
typename InputIt,
109 typename std::enable_if<
111 InputIt>::type * =
nullptr>
112 void assign(InputIt first, InputIt last);
113 void assign(std::initializer_list<T> ilist);
116 void assign(
const std::vector<T> &other);
122 reference
at(size_type n);
123 const_reference
at(size_type n)
const;
134 const value_type *
data() const noexcept;
135 const value_type *
cdata() const noexcept;
139 const_iterator
begin() const noexcept;
142 const_iterator
end() const noexcept;
143 const_iterator
cend() const noexcept;
145 const_reverse_iterator
rbegin() const noexcept;
146 const_reverse_iterator
crbegin() const noexcept;
148 const_reverse_iterator
rend() const noexcept;
149 const_reverse_iterator
crend() const noexcept;
154 size_type snapshot_size);
155 slice<const_iterator>
range(size_type start, size_type n) const;
159 constexpr
bool empty() const noexcept;
160 size_type
size() const noexcept;
172 template <typename InputIt,
173 typename
std::enable_if<
174 detail::is_input_iterator<InputIt>::value,
175 InputIt>::type * =
nullptr>
178 template <class... Args>
180 template <class... Args>
188 void resize(size_type count, const value_type &value);
193 template <typename P>
194 struct single_element_iterator {
195 using iterator_category = std::input_iterator_tag;
196 using value_type = P;
197 using difference_type = std::ptrdiff_t;
198 using pointer =
const P *;
199 using reference =
const P &;
204 single_element_iterator(
const P *ptr, std::size_t count = 0)
205 : ptr(ptr), count(count)
209 reference operator*()
219 single_element_iterator &
226 single_element_iterator
229 single_element_iterator tmp =
230 single_element_iterator(ptr, count);
236 operator-(
const single_element_iterator &rhs)
238 return count - rhs.count;
242 operator!=(
const single_element_iterator &rhs)
244 return ptr != rhs.ptr || count != rhs.count;
252 template <
typename... Args>
254 template <
typename InputIt,
255 typename std::enable_if<
257 InputIt>::type * =
nullptr>
261 template <typename InputIt>
267 template <typename InputIt>
273 p<size_type> _capacity;
280 template <typename T>
287 template <typename T>
288 bool operator==(const
vector<T> &lhs, const
vector<T> &rhs);
289 template <typename T>
290 bool operator!=(const
vector<T> &lhs, const
vector<T> &rhs);
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);
304 template <typename T>
306 template <typename T>
308 template <typename T>
310 template <typename T>
312 template <typename T>
314 template <typename T>
321 template <typename T>
323 template <typename T>
325 template <typename T>
327 template <typename T>
329 template <typename T>
331 template <typename T>
343 template <typename T>
372 template <
typename T>
401 template <
typename T>
435 template <
typename T>
436 template <
typename InputIt,
437 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
446 alloc(
static_cast<size_type
>(std::distance(first, last)));
468 template <
typename T>
499 template <
typename T>
506 _capacity = other.capacity();
507 _size = other.size();
508 other._data =
nullptr;
509 other._capacity = other._size = 0;
529 template <
typename T>
553 template <
typename T>
570 template <
typename T>
589 template <
typename T>
593 assign(std::move(other));
607 template <
typename T>
611 assign(ilist.begin(), ilist.end());
628 template <
typename T>
653 template <
typename T>
660 if (count <= capacity()) {
667 size_type size_old = _size;
668 add_data_to_tx(0, size_old);
673 static_cast<size_type
>(size_old)),
676 if (count > size_old) {
677 add_data_to_tx(size_old, count - size_old);
678 construct_at_end(count - size_old, value);
685 construct_at_end(count, value);
708 template <
typename T>
709 template <
typename InputIt,
710 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
717 size_type size_new =
static_cast<size_type
>(std::distance(first, last));
720 if (size_new <= capacity()) {
727 size_type size_old = _size;
728 add_data_to_tx(0, size_old);
731 bool growing = size_new > size_old;
734 add_data_to_tx(size_old, size_new - size_old);
737 std::advance(mid, size_old);
740 iterator shrink_to = std::copy(first, mid, &_data[0]);
743 construct_at_end(mid, last);
745 shrink(
static_cast<size_type
>(std::distance(
751 construct_at_end(first, last);
771 template <
typename T>
775 assign(ilist.begin(), ilist.end());
789 template <
typename T>
808 template <
typename T>
821 _capacity = other._capacity;
824 other._data =
nullptr;
825 other._capacity = other._size = 0;
841 template <
typename T>
845 assign(other.cbegin(), other.cend());
857 template <
typename T>
875 template <
typename T>
876 typename vector<T>::reference
880 throw std::out_of_range(
"vector::at");
882 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)],
883 1, POBJ_XADD_ASSUME_INITIALIZED);
885 return _data[
static_cast<difference_type
>(n)];
897 template <
typename T>
898 typename vector<T>::const_reference
902 throw std::out_of_range(
"vector::at");
904 return _data[
static_cast<difference_type
>(n)];
919 template <
typename T>
920 typename vector<T>::const_reference
924 throw std::out_of_range(
"vector::const_at");
926 return _data[
static_cast<difference_type
>(n)];
940 template <
typename T>
943 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)],
944 1, POBJ_XADD_ASSUME_INITIALIZED);
946 return _data[
static_cast<difference_type
>(n)];
956 template <
typename T>
959 return _data[
static_cast<difference_type
>(n)];
970 template <
typename T>
971 typename vector<T>::reference
974 detail::conditional_add_to_tx(&_data[0], 1,
975 POBJ_XADD_ASSUME_INITIALIZED);
985 template <
typename T>
986 typename vector<T>::const_reference
999 template <
typename T>
1000 typename vector<T>::const_reference
1014 template <
typename T>
1015 typename vector<T>::reference
1018 detail::conditional_add_to_tx(
1019 &_data[
static_cast<difference_type
>(size() - 1)], 1,
1020 POBJ_XADD_ASSUME_INITIALIZED);
1022 return _data[
static_cast<difference_type
>(size() - 1)];
1030 template <
typename T>
1031 typename vector<T>::const_reference
1034 return _data[
static_cast<difference_type
>(size() - 1)];
1044 template <
typename T>
1045 typename vector<T>::const_reference
1048 return _data[
static_cast<difference_type
>(size() - 1)];
1060 template <
typename T>
1061 typename vector<T>::value_type *
1064 add_data_to_tx(0, _size);
1074 template <
typename T>
1075 const typename vector<T>::value_type *
1088 template <
typename T>
1089 const typename vector<T>::value_type *
1100 template <
typename T>
1112 template <
typename T>
1113 typename vector<T>::const_iterator
1116 return const_iterator(_data.get());
1126 template <
typename T>
1127 typename vector<T>::const_iterator
1130 return const_iterator(_data.get());
1138 template <
typename T>
1142 return iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1150 template <
typename T>
1151 typename vector<T>::const_iterator
1154 return const_iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1164 template <
typename T>
1165 typename vector<T>::const_iterator
1168 return const_iterator(_data.get() +
static_cast<std::ptrdiff_t
>(_size));
1176 template <
typename T>
1177 typename vector<T>::reverse_iterator
1180 return reverse_iterator(
end());
1188 template <
typename T>
1189 typename vector<T>::const_reverse_iterator
1192 return const_reverse_iterator(
cend());
1202 template <
typename T>
1203 typename vector<T>::const_reverse_iterator
1206 return const_reverse_iterator(
cend());
1215 template <
typename T>
1216 typename vector<T>::reverse_iterator
1219 return reverse_iterator(
begin());
1228 template <
typename T>
1229 typename vector<T>::const_reverse_iterator
1232 return const_reverse_iterator(
cbegin());
1243 template <
typename T>
1244 typename vector<T>::const_reverse_iterator
1247 return const_reverse_iterator(
cbegin());
1263 template <
typename T>
1267 if (start + n > size())
1268 throw std::out_of_range(
"vector::range");
1270 detail::conditional_add_to_tx(cdata() + start, n,
1271 POBJ_XADD_ASSUME_INITIALIZED);
1273 return {_data.get() + start, _data.get() + start + n};
1291 template <
typename T>
1295 if (start + n > size())
1296 throw std::out_of_range(
"vector::range");
1298 if (snapshot_size > n)
1302 _data.get() + start, n,
1305 _data.get() + start, n,
1320 template <
typename T>
1324 if (start + n > size())
1325 throw std::out_of_range(
"vector::range");
1327 return {const_iterator(cdata() + start),
1328 const_iterator(cdata() + start + n)};
1342 template <
typename T>
1346 if (start + n > size())
1347 throw std::out_of_range(
"vector::crange");
1349 return {const_iterator(cdata() + start),
1350 const_iterator(cdata() + start + n)};
1358 template <
typename T>
1368 template <
typename T>
1369 typename vector<T>::size_type
1379 template <
typename T>
1380 constexpr
typename vector<T>::size_type
1383 return PMEMOBJ_MAX_ALLOC_SIZE /
sizeof(value_type);
1404 template <
typename T>
1408 if (capacity_new <= _capacity)
1418 template <
typename T>
1419 typename vector<T>::size_type
1439 template <
typename T>
1443 size_type capacity_new = size();
1444 if (capacity() == capacity_new)
1459 template <
typename T>
1479 template <
typename T>
1483 if (_data ==
nullptr)
1514 template <
typename T>
1518 return insert(pos, 1, value);
1545 template <
typename T>
1551 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1554 internal_insert(idx, std::make_move_iterator(&value),
1555 std::make_move_iterator(&value + 1));
1558 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1589 template <
typename T>
1595 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1599 idx, single_element_iterator<value_type>(&value, 0),
1600 single_element_iterator<value_type>(&value, count));
1603 return iterator(_data.get() +
static_cast<difference_type
>(idx));
1640 template <
typename T>
1641 template <
typename InputIt,
1642 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1649 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1653 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1684 template <
typename T>
1688 return insert(pos, ilist.begin(), ilist.end());
1718 template <
typename T>
1719 template <
class... Args>
1725 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1734 noexcept(T(std::forward<Args>(args)...))>
1735 tmp(std::forward<Args>(args)...);
1737 auto &tmp_ref = tmp.get();
1739 internal_insert(idx, std::make_move_iterator(&tmp_ref),
1740 std::make_move_iterator(&tmp_ref + 1));
1743 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1768 template <
typename T>
1769 template <
class... Args>
1770 typename vector<T>::reference
1781 if (_size == _capacity) {
1782 realloc(get_recommended_capacity(_size + 1));
1784 add_data_to_tx(size(), 1);
1787 construct_at_end(1, std::forward<Args>(args)...);
1812 template <
typename T>
1816 return erase(pos, pos + 1);
1841 template <
typename T>
1845 size_type idx =
static_cast<size_type
>(
1846 std::distance(const_iterator(_data.get()), first));
1847 size_type count =
static_cast<size_type
>(std::distance(first, last));
1850 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1859 add_data_to_tx(idx, _size - idx);
1861 pointer move_begin =
1862 &_data[
static_cast<difference_type
>(idx + count)];
1863 pointer move_end = &_data[
static_cast<difference_type
>(size())];
1864 pointer dest = &_data[
static_cast<difference_type
>(idx)];
1866 std::move(move_begin, move_end, dest);
1871 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1889 template <
typename T>
1893 emplace_back(value);
1912 template <
typename T>
1916 emplace_back(std::move(value));
1929 template <
typename T>
1956 template <
typename T>
1965 if (_capacity < count)
1967 construct_at_end(count - _size);
1989 template <
typename T>
1993 if (_capacity == count)
2001 if (_capacity < count)
2003 construct_at_end(count - _size, value);
2011 template <
typename T>
2017 std::swap(this->_data, other._data);
2018 std::swap(this->_size, other._size);
2019 std::swap(this->_capacity, other._capacity);
2040 template <
typename T>
2044 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2045 assert(_data ==
nullptr);
2048 if (capacity_new > max_size())
2049 throw std::length_error(
"New capacity exceeds max size.");
2051 _capacity = capacity_new;
2053 if (capacity_new == 0)
2062 pmemobj_tx_alloc(
sizeof(value_type) * capacity_new,
2063 detail::type_num<value_type>());
2065 if (res ==
nullptr) {
2066 if (errno == ENOMEM)
2068 "Failed to allocate persistent memory object")
2069 .with_pmemobj_errormsg();
2072 "Failed to allocate persistent memory object")
2073 .with_pmemobj_errormsg();
2085 template <
typename T>
2089 if (
nullptr == pmemobj_pool_by_ptr(
this))
2100 template <
typename T>
2104 if (pmemobj_tx_stage() != TX_STAGE_WORK)
2106 "Function called out of transaction scope.");
2127 template <
typename T>
2128 template <
typename... Args>
2132 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2133 assert(_capacity >= count + _size);
2135 pointer dest = _data.get() + size();
2136 const_pointer
end = dest + count;
2137 for (; dest !=
end; ++dest)
2138 detail::create<value_type, Args...>(
2139 dest, std::forward<Args>(args)...);
2165 template <
typename T>
2166 template <
typename InputIt,
2167 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2172 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2173 difference_type range_size = std::distance(first, last);
2174 assert(range_size >= 0);
2175 assert(_capacity >=
static_cast<size_type
>(range_size) + _size);
2177 pointer dest = _data.get() + size();
2178 _size +=
static_cast<size_type
>(range_size);
2179 while (first != last)
2180 detail::create<value_type>(dest++, *first++);
2198 template <
typename T>
2202 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2204 if (_data !=
nullptr) {
2206 if (pmemobj_tx_free(*_data.raw_ptr()) != 0)
2208 "failed to delete persistent memory object")
2209 .with_pmemobj_errormsg();
2222 template <
typename T>
2226 auto pop = pmemobj_pool_by_ptr(
this);
2227 assert(pop !=
nullptr);
2238 template <
typename T>
2242 while (first != last && d_last >=
cend())
2243 detail::create<value_type>(--d_last, std::move(*(--last)));
2246 std::move_backward(first, last, d_last);
2256 template <
typename T>
2257 template <
typename InputIt>
2261 auto count =
static_cast<size_type
>(std::distance(first, last));
2262 auto dest = _data.get() + idx;
2263 auto initialized_slots =
static_cast<size_type
>(
cend() - dest);
2267 dest = std::copy_n(first, (std::min)(initialized_slots, count),
2270 std::advance(first, (std::min)(initialized_slots, count));
2273 while (first != last)
2274 detail::create<value_type>(dest++, *first++);
2299 template <
typename T>
2300 template <
typename InputIt>
2304 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2306 auto count =
static_cast<size_type
>(std::distance(first, last));
2308 if (_capacity >= size() + count) {
2309 pointer dest = _data.get() +
2310 static_cast<difference_type
>(size() + count);
2311 pointer
begin = _data.get() +
static_cast<difference_type
>(idx);
2313 _data.get() +
static_cast<difference_type
>(size());
2315 add_data_to_tx(idx, size() - idx + count);
2318 move_elements_backward(
begin,
end, dest);
2321 construct_or_assign(idx, first, last);
2327 add_data_to_tx(0, _size);
2329 auto old_data = _data;
2330 auto old_size = _size;
2331 pointer old_begin = _data.get();
2333 _data.get() +
static_cast<difference_type
>(idx);
2335 _data.get() +
static_cast<difference_type
>(size());
2338 _size = _capacity = 0;
2340 alloc(get_recommended_capacity(old_size + count));
2343 construct_at_end(std::make_move_iterator(old_begin),
2344 std::make_move_iterator(old_mid));
2347 construct_at_end(first, last);
2350 construct_at_end(std::make_move_iterator(old_mid),
2351 std::make_move_iterator(old_end));
2354 for (size_type i = 0; i < old_size; ++i)
2355 detail::destroy<value_type>(
2356 old_data[
static_cast<difference_type
>(i)]);
2357 if (pmemobj_tx_free(old_data.raw()) != 0)
2359 "failed to delete persistent memory object")
2360 .with_pmemobj_errormsg();
2382 template <
typename T>
2386 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2392 if (_data ==
nullptr)
2393 return alloc(capacity_new);
2399 add_data_to_tx(0, _size);
2401 auto old_data = _data;
2402 auto old_size = _size;
2403 pointer old_begin = _data.get();
2404 pointer old_end = capacity_new < _size
2405 ? &_data[
static_cast<difference_type
>(capacity_new)]
2406 : &_data[
static_cast<difference_type
>(size())];
2409 _size = _capacity = 0;
2411 alloc(capacity_new);
2413 construct_at_end(std::make_move_iterator(old_begin),
2414 std::make_move_iterator(old_end));
2417 for (size_type i = 0; i < old_size; ++i)
2418 detail::destroy<value_type>(
2419 old_data[
static_cast<difference_type
>(i)]);
2420 if (pmemobj_tx_free(old_data.raw()) != 0)
2422 "failed to delete persistent memory object")
2423 .with_pmemobj_errormsg();
2432 template <
typename T>
2433 typename vector<T>::size_type
2436 return detail::next_pow_2(at_least);
2455 template <
typename T>
2459 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2460 assert(size_new <= _size);
2462 add_data_to_tx(size_new, _size - size_new);
2464 for (size_type i = size_new; i < _size; ++i)
2465 detail::destroy<value_type>(
2466 _data[
static_cast<difference_type
>(i)]);
2479 template <
typename T>
2483 assert(idx_first + num <= capacity());
2485 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2487 assert(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_data.get() + idx_first,
2488 num *
sizeof(T)) == 0);
2491 auto initialized_num = size() - idx_first;
2494 detail::conditional_add_to_tx(_data.get() + idx_first,
2495 (std::min)(initialized_num, num),
2496 POBJ_XADD_ASSUME_INITIALIZED);
2498 if (num > initialized_num) {
2500 detail::conditional_add_to_tx(_data.get() + size(),
2501 num - initialized_num,
2502 POBJ_XADD_NO_SNAPSHOT);
2517 template <
typename T>
2536 template <
typename T>
2540 return !(lhs == rhs);
2553 template <
typename T>
2557 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2571 template <
typename T>
2575 return !(rhs < lhs);
2589 template <
typename T>
2606 template <
typename T>
2610 return !(lhs < rhs);
2624 template <
typename T>
2628 return lhs.
size() == rhs.size() &&
2629 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2643 template <
typename T>
2647 return !(lhs == rhs);
2660 template <
typename T>
2664 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2678 template <
typename T>
2682 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2697 template <
typename T>
2701 return !(lhs <= rhs);
2714 template <
typename T>
2718 return !(lhs < rhs);
2732 template <
typename T>
2750 template <
typename T>
2754 return !(lhs == rhs);
2767 template <
typename T>
2784 template <
typename T>
2788 return !(rhs < lhs);
2802 template <
typename T>
2819 template <
typename T>
2823 return !(lhs < rhs);
2832 template <
typename T>