38 #ifndef LIBPMEMOBJ_CPP_VECTOR_HPP
39 #define LIBPMEMOBJ_CPP_VECTOR_HPP
51 #include <libpmemobj.h>
64 namespace experimental
76 using size_type = std::size_t;
77 using difference_type = std::ptrdiff_t;
78 using reference = value_type &;
79 using const_reference =
const value_type &;
80 using pointer = value_type *;
81 using const_pointer =
const value_type *;
83 using const_iterator = const_pointer;
84 using reverse_iterator = std::reverse_iterator<iterator>;
85 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
89 vector(size_type count,
const value_type &value);
91 template <
typename InputIt,
92 typename std::enable_if<
94 InputIt>::type * =
nullptr>
98 vector(std::initializer_list<T> init);
108 void assign(size_type count,
const T &value);
109 template <
typename InputIt,
110 typename std::enable_if<
112 InputIt>::type * =
nullptr>
113 void assign(InputIt first, InputIt last);
114 void assign(std::initializer_list<T> ilist);
117 void assign(
const std::vector<T> &other);
123 reference
at(size_type n);
124 const_reference
at(size_type n)
const;
135 const value_type *
data() const noexcept;
136 const value_type *
cdata() const noexcept;
140 const_iterator
begin() const noexcept;
143 const_iterator
end() const noexcept;
144 const_iterator
cend() const noexcept;
146 const_reverse_iterator
rbegin() const noexcept;
147 const_reverse_iterator
crbegin() const noexcept;
149 const_reverse_iterator
rend() const noexcept;
150 const_reverse_iterator
crend() const noexcept;
155 range(size_type start, size_type n, size_type snapshot_size);
156 slice<const_iterator>
range(size_type start, size_type n) const;
160 constexpr
bool empty() const noexcept;
161 size_type
size() const noexcept;
173 template <typename InputIt,
174 typename std::enable_if<
175 detail::is_input_iterator<InputIt>::value,
176 InputIt>::type * =
nullptr>
179 template <class... Args>
181 template <class... Args>
189 void resize(size_type count, const value_type &value);
197 template <typename... Args>
198 void construct(size_type idx, size_type count, Args &&... args);
199 template <typename InputIt,
200 typename std::enable_if<
201 detail::is_input_iterator<InputIt>::value,
202 InputIt>::type * =
nullptr>
204 template <typename InputIt,
205 typename std::enable_if<
206 detail::is_input_iterator<InputIt>::value,
207 InputIt>::type * =
nullptr>
221 p<size_type> _capacity;
225 template <typename T>
232 template <typename T>
233 bool operator==(const
vector<T> &lhs, const
vector<T> &rhs);
234 template <typename T>
235 bool operator!=(const
vector<T> &lhs, const
vector<T> &rhs);
236 template <typename T>
237 bool operator<(const
vector<T> &lhs, const
vector<T> &rhs);
238 template <typename T>
239 bool operator<=(const
vector<T> &lhs, const
vector<T> &rhs);
240 template <typename T>
241 bool operator>(const
vector<T> &lhs, const
vector<T> &rhs);
242 template <typename T>
243 bool operator>=(const
vector<T> &lhs, const
vector<T> &rhs);
249 template <typename T>
250 bool operator==(const
vector<T> &lhs, const std::
vector<T> &rhs);
251 template <typename T>
252 bool operator!=(const
vector<T> &lhs, const std::
vector<T> &rhs);
253 template <typename T>
254 bool operator<(const
vector<T> &lhs, const std::
vector<T> &rhs);
255 template <typename T>
256 bool operator<=(const
vector<T> &lhs, const std::
vector<T> &rhs);
257 template <typename T>
258 bool operator>(const
vector<T> &lhs, const std::
vector<T> &rhs);
259 template <typename T>
260 bool operator>=(const
vector<T> &lhs, const std::
vector<T> &rhs);
266 template <typename T>
267 bool operator==(const std::
vector<T> &lhs, const
vector<T> &rhs);
268 template <typename T>
269 bool operator!=(const std::
vector<T> &lhs, const
vector<T> &rhs);
270 template <typename T>
271 bool operator<(const std::
vector<T> &lhs, const
vector<T> &rhs);
272 template <typename T>
273 bool operator<=(const std::
vector<T> &lhs, const
vector<T> &rhs);
274 template <typename T>
275 bool operator>(const std::
vector<T> &lhs, const
vector<T> &rhs);
276 template <typename T>
277 bool operator>=(const std::
vector<T> &lhs, const
vector<T> &rhs);
287 template <typename T>
315 template <
typename T>
343 template <
typename T>
376 template <
typename T>
377 template <
typename InputIt,
378 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
387 alloc(
static_cast<size_type
>(std::distance(first, last)));
408 template <
typename T>
438 template <
typename T>
445 _capacity = other.capacity();
446 _size = other.size();
447 other._data =
nullptr;
448 other._capacity = other._size = 0;
467 template <
typename T>
490 template <
typename T>
507 template <
typename T>
526 template <
typename T>
530 assign(std::move(other));
544 template <
typename T>
548 assign(ilist.begin(), ilist.end());
565 template <
typename T>
590 template <
typename T>
597 if (count <= capacity()) {
604 size_type size_old = _size;
605 snapshot_data(0, size_old);
610 static_cast<size_type
>(size_old)),
613 if (count > size_old) {
614 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
621 VALGRIND_PMC_ADD_TO_TX(
622 &_data[
static_cast<difference_type
>(
624 sizeof(T) * (count - size_old));
627 construct(size_old, count - size_old, value);
636 pb.
persist(&_data[
static_cast<difference_type
>(
638 sizeof(T) * (count - size_old));
645 construct(0, count, value);
668 template <
typename T>
669 template <
typename InputIt,
670 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
677 size_type size_new =
static_cast<size_type
>(std::distance(first, last));
680 if (size_new <= capacity()) {
687 size_type size_old = _size;
688 snapshot_data(0, size_old);
691 bool growing = size_new > size_old;
694 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
701 VALGRIND_PMC_ADD_TO_TX(
702 &_data[
static_cast<difference_type
>(
704 sizeof(T) * (size_new - size_old));
708 std::advance(mid, size_old);
711 iterator shrink_to = std::copy(first, mid, &_data[0]);
714 construct_range_copy(size_old, mid, last);
723 pb.
persist(&_data[
static_cast<difference_type
>(
725 sizeof(T) * (size_new - size_old));
727 shrink(
static_cast<size_type
>(std::distance(
733 construct_range_copy(0, first, last);
753 template <
typename T>
757 assign(ilist.begin(), ilist.end());
771 template <
typename T>
790 template <
typename T>
803 _capacity = other._capacity;
806 other._data =
nullptr;
807 other._capacity = other._size = 0;
823 template <
typename T>
827 assign(other.cbegin(), other.cend());
839 template <
typename T>
857 template <
typename T>
858 typename vector<T>::reference
862 throw std::out_of_range(
"vector::at");
864 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)]);
866 return _data[
static_cast<difference_type
>(n)];
878 template <
typename T>
879 typename vector<T>::const_reference
883 throw std::out_of_range(
"vector::at");
885 return _data[
static_cast<difference_type
>(n)];
900 template <
typename T>
901 typename vector<T>::const_reference
905 throw std::out_of_range(
"vector::const_at");
907 return _data[
static_cast<difference_type
>(n)];
921 template <
typename T>
924 detail::conditional_add_to_tx(&_data[
static_cast<difference_type
>(n)]);
926 return _data[
static_cast<difference_type
>(n)];
936 template <
typename T>
939 return _data[
static_cast<difference_type
>(n)];
950 template <
typename T>
951 typename vector<T>::reference
954 detail::conditional_add_to_tx(&_data[0]);
964 template <
typename T>
965 typename vector<T>::const_reference
978 template <
typename T>
979 typename vector<T>::const_reference
993 template <
typename T>
994 typename vector<T>::reference
997 detail::conditional_add_to_tx(
998 &_data[
static_cast<difference_type
>(size() - 1)]);
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 snapshot_data(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);
1250 return {_data.get() + start, _data.get() + start + n};
1268 template <
typename T>
1272 if (start + n > size())
1273 throw std::out_of_range(
"vector::range");
1275 if (snapshot_size > n)
1279 _data.get() + start, n,
1282 _data.get() + start, n,
1297 template <
typename T>
1301 if (start + n > size())
1302 throw std::out_of_range(
"vector::range");
1304 return {const_iterator(cdata() + start),
1305 const_iterator(cdata() + start + n)};
1319 template <
typename T>
1323 if (start + n > size())
1324 throw std::out_of_range(
"vector::crange");
1326 return {const_iterator(cdata() + start),
1327 const_iterator(cdata() + start + n)};
1335 template <
typename T>
1345 template <
typename T>
1346 typename vector<T>::size_type
1356 template <
typename T>
1357 constexpr
typename vector<T>::size_type
1360 return PMEMOBJ_MAX_ALLOC_SIZE /
sizeof(value_type);
1381 template <
typename T>
1385 if (capacity_new <= _capacity)
1395 template <
typename T>
1396 typename vector<T>::size_type
1416 template <
typename T>
1420 size_type capacity_new = size();
1421 if (capacity() == capacity_new)
1436 template <
typename T>
1456 template <
typename T>
1460 if (_data ==
nullptr)
1491 template <
typename T>
1495 return insert(pos, 1, value);
1522 template <
typename T>
1528 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1532 construct(idx, 1, std::move(value));
1535 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1566 template <
typename T>
1572 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1575 insert_gap(idx, count);
1576 construct(idx, count, value);
1579 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1616 template <
typename T>
1617 template <
typename InputIt,
1618 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1625 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1626 size_type gap_size =
static_cast<size_type
>(std::distance(first, last));
1629 insert_gap(idx, gap_size);
1630 construct_range_copy(idx, first, last);
1633 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1664 template <
typename T>
1668 return insert(pos, ilist.begin(), ilist.end());
1698 template <
typename T>
1699 template <
class... Args>
1705 size_type idx =
static_cast<size_type
>(std::distance(
cbegin(), pos));
1714 noexcept(T(std::forward<Args>(args)...))>
1715 tmp(std::forward<Args>(args)...);
1718 construct(idx, 1, std::move(tmp.get()));
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 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
1768 VALGRIND_PMC_ADD_TO_TX(
1769 &_data[
static_cast<difference_type
>(size())],
1774 construct(size(), 1, std::forward<Args>(args)...);
1781 pb.
persist(&_data[
static_cast<difference_type
>(size() - 1)],
1807 template <
typename T>
1811 return erase(pos, pos + 1);
1836 template <
typename T>
1840 size_type idx =
static_cast<size_type
>(
1841 std::distance(const_iterator(&_data[0]), first));
1842 size_type count =
static_cast<size_type
>(std::distance(first, last));
1845 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1854 snapshot_data(idx, _size);
1856 pointer move_begin =
1857 &_data[
static_cast<difference_type
>(idx + count)];
1858 pointer move_end = &_data[
static_cast<difference_type
>(size())];
1859 pointer dest = &_data[
static_cast<difference_type
>(idx)];
1861 std::move(move_begin, move_end, dest);
1866 return iterator(&_data[
static_cast<difference_type
>(idx)]);
1884 template <
typename T>
1888 emplace_back(value);
1907 template <
typename T>
1911 emplace_back(std::move(value));
1924 template <
typename T>
1951 template <
typename T>
1960 if (_capacity < count)
1962 construct(_size, count - _size);
1984 template <
typename T>
1988 if (_capacity == count)
1996 if (_capacity < count)
1998 construct(_size, count - _size, value);
2006 template <
typename T>
2012 std::swap(this->_data, other._data);
2013 std::swap(this->_size, other._size);
2014 std::swap(this->_capacity, other._capacity);
2035 template <
typename T>
2039 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2040 assert(_data ==
nullptr);
2043 if (capacity_new > max_size())
2044 throw std::length_error(
"New capacity exceeds max size.");
2046 _capacity = capacity_new;
2048 if (capacity_new == 0)
2057 pmemobj_tx_alloc(
sizeof(value_type) * capacity_new,
2058 detail::type_num<value_type>());
2062 "Failed to allocate persistent memory object");
2073 template <
typename T>
2077 if (
nullptr == pmemobj_pool_by_ptr(
this))
2088 template <
typename T>
2092 if (pmemobj_tx_stage() != TX_STAGE_WORK)
2094 "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() + idx;
2125 const_pointer
end = dest + count;
2126 for (; dest !=
end; ++dest)
2127 detail::create<value_type, Args...>(
2128 dest, std::forward<Args>(args)...);
2155 template <
typename T>
2156 template <
typename InputIt,
2157 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2162 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2163 difference_type range_size = std::distance(first, last);
2164 assert(range_size >= 0);
2165 assert(_capacity >=
static_cast<size_type
>(range_size) + _size);
2167 pointer dest = _data.get() + idx;
2168 _size +=
static_cast<size_type
>(range_size);
2169 while (first != last)
2170 detail::create<value_type>(dest++, std::move(*first++));
2194 template <
typename T>
2195 template <
typename InputIt,
2196 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2201 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2202 difference_type diff = std::distance(first, last);
2204 assert(_capacity >=
static_cast<size_type
>(diff) + _size);
2206 pointer dest = _data.get() + idx;
2207 _size +=
static_cast<size_type
>(diff);
2208 while (first != last)
2209 detail::create<value_type>(dest++, *first++);
2227 template <
typename T>
2231 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2233 if (_data !=
nullptr) {
2235 if (pmemobj_tx_free(*_data.raw_ptr()) != 0)
2237 "failed to delete persistent memory object");
2250 template <
typename T>
2254 auto pop = pmemobj_pool_by_ptr(
this);
2255 assert(pop !=
nullptr);
2277 template <
typename T>
2281 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2283 if (_capacity >= _size + count) {
2285 &_data[
static_cast<difference_type
>(size() + count)];
2286 pointer
begin = &_data[
static_cast<difference_type
>(idx)];
2287 pointer
end = &_data[
static_cast<difference_type
>(size())];
2300 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
2301 VALGRIND_MAKE_MEM_DEFINED(
end,
sizeof(T) * count);
2303 snapshot_data(idx, _size + count);
2305 std::move_backward(
begin,
end, dest);
2311 snapshot_data(0, _size);
2313 auto old_data = _data;
2314 auto old_size = _size;
2315 pointer old_begin = &_data[0];
2316 pointer old_mid = &_data[
static_cast<difference_type
>(idx)];
2317 pointer old_end = &_data[
static_cast<difference_type
>(size())];
2320 _size = _capacity = 0;
2322 alloc(get_recommended_capacity(old_size + count));
2324 construct_range(0, old_begin, old_mid);
2325 construct_range(idx + count, old_mid, old_end);
2328 for (size_type i = 0; i < old_size; ++i)
2329 detail::destroy<value_type>(
2330 old_data[
static_cast<difference_type
>(i)]);
2331 if (pmemobj_tx_free(old_data.raw()) != 0)
2333 "failed to delete persistent memory object");
2354 template <
typename T>
2358 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2364 snapshot_data(0, _size);
2366 auto old_data = _data;
2367 auto old_size = _size;
2368 pointer old_begin = &_data[0];
2369 pointer old_end = capacity_new < _size
2370 ? &_data[
static_cast<difference_type
>(capacity_new)]
2371 : &_data[
static_cast<difference_type
>(size())];
2374 _size = _capacity = 0;
2376 alloc(capacity_new);
2378 construct_range(0, old_begin, old_end);
2381 for (size_type i = 0; i < old_size; ++i)
2382 detail::destroy<value_type>(
2383 old_data[
static_cast<difference_type
>(i)]);
2384 if (pmemobj_tx_free(old_data.raw()) != 0)
2386 "failed to delete persistent memory object");
2395 template <
typename T>
2396 typename vector<T>::size_type
2399 return detail::next_pow_2(at_least);
2418 template <
typename T>
2422 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2423 assert(size_new <= _size);
2425 snapshot_data(size_new, _size);
2427 for (size_type i = size_new; i < _size; ++i)
2428 detail::destroy<value_type>(
2429 _data[
static_cast<difference_type
>(i)]);
2442 template <
typename T>
2446 detail::conditional_add_to_tx(_data.get() + idx_first,
2447 idx_last - idx_first);
2461 template <
typename T>
2480 template <
typename T>
2484 return !(lhs == rhs);
2497 template <
typename T>
2501 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2515 template <
typename T>
2519 return !(rhs < lhs);
2533 template <
typename T>
2550 template <
typename T>
2554 return !(lhs < rhs);
2568 template <
typename T>
2572 return lhs.
size() == rhs.size() &&
2573 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2587 template <
typename T>
2591 return !(lhs == rhs);
2604 template <
typename T>
2608 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2622 template <
typename T>
2626 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2641 template <
typename T>
2645 return !(lhs <= rhs);
2658 template <
typename T>
2662 return !(lhs < rhs);
2676 template <
typename T>
2694 template <
typename T>
2698 return !(lhs == rhs);
2711 template <
typename T>
2728 template <
typename T>
2732 return !(rhs < lhs);
2746 template <
typename T>
2763 template <
typename T>
2767 return !(lhs < rhs);
2776 template <
typename T>