9 #ifndef LIBPMEMOBJ_SEGMENT_VECTOR_HPP
10 #define LIBPMEMOBJ_SEGMENT_VECTOR_HPP
17 #include <libpmemobj++/detail/temp_value.hpp>
35 namespace segment_vector_internal
45 template <
typename Container,
bool is_const>
49 using iterator_category = std::random_access_iterator_tag;
50 using difference_type = std::ptrdiff_t;
51 using table_type = Container;
52 using size_type =
typename table_type::size_type;
53 using value_type =
typename table_type::value_type;
56 typename std::conditional<is_const,
const table_type *,
59 typename std::conditional<is_const,
60 typename table_type::const_reference,
61 typename table_type::reference>::type;
63 typename std::conditional<is_const,
64 typename table_type::const_pointer,
65 typename table_type::pointer>::type;
85 template <
typename U = void,
86 typename =
typename std::enable_if<is_const, U>::type>
131 template <
typename Container,
bool is_const>
133 : table(
nullptr), index()
141 template <
typename Container,
bool is_const>
143 size_type idx) noexcept
144 : table(tab), index(idx)
152 template <
typename Container,
bool is_const>
155 : table(other.table), index(other.index)
160 template <
typename Container,
bool is_const>
161 template <
typename U,
typename>
164 : table(other.table), index(other.index)
173 template <
typename Container,
bool is_const>
186 template <
typename Container,
bool is_const>
190 auto iterator = *
this;
200 template <
typename Container,
bool is_const>
212 template <
typename Container,
bool is_const>
216 index +=
static_cast<size_type
>(idx);
225 template <
typename Container,
bool is_const>
238 template <
typename Container,
bool is_const>
242 auto iterator = *
this;
252 template <
typename Container,
bool is_const>
264 template <
typename Container,
bool is_const>
268 index -=
static_cast<size_type
>(idx);
277 template <
typename Container,
bool is_const>
279 typename segment_iterator<Container, is_const>::difference_type
283 return static_cast<difference_type
>(index + rhs.index);
291 template <
typename Container,
bool is_const>
293 typename segment_iterator<Container, is_const>::difference_type
297 return static_cast<difference_type
>(index - rhs.index);
307 template <
typename Container,
bool is_const>
313 return (table == rhs.table) && (index == rhs.index);
324 template <
typename Container,
bool is_const>
330 return (table != rhs.table) || (index != rhs.index);
343 template <
typename Container,
bool is_const>
349 if (table != rhs.table)
350 throw std::invalid_argument(
"segment_iterator::operator<");
352 return index < rhs.index;
366 template <
typename Container,
bool is_const>
372 if (table != rhs.table)
373 throw std::invalid_argument(
"segment_iterator::operator>");
375 return index > rhs.index;
389 template <
typename Container,
bool is_const>
395 if (table != rhs.table)
396 throw std::invalid_argument(
"segment_iterator::operator<=");
398 return index <= rhs.index;
412 template <
typename Container,
bool is_const>
418 if (table != rhs.table)
419 throw std::invalid_argument(
"segment_iterator::operator>=");
421 return index >= rhs.index;
427 template <
typename Container,
bool is_const>
428 typename segment_iterator<Container, is_const>::reference
431 return table->operator[](index);
437 template <
typename Container,
bool is_const>
438 typename segment_iterator<Container, is_const>::pointer
456 segment_vector_internal::exponential_size_policy<
467 template <
size_t SegmentSize = 1024,
471 SegmentType, SegmentSize>;
503 template <
typename T,
typename Policy = exponential_size_vector_policy<>>
507 using policy_type = Policy;
508 using segment_type =
typename policy_type::template segment_type<T>;
509 using segment_vector_type =
510 typename policy_type::template segment_vector_type<T>;
512 using policy = policy_type;
513 using storage = policy_type;
516 using value_type = T;
517 using size_type = std::size_t;
518 using difference_type = std::ptrdiff_t;
519 using reference = value_type &;
520 using const_reference =
const value_type &;
521 using pointer = value_type *;
522 using const_pointer =
const value_type *;
528 using reverse_iterator = std::reverse_iterator<iterator>;
529 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
535 template <
typename InputIt,
536 typename std::enable_if<
538 InputIt>::type * =
nullptr>
552 void assign(size_type count, const_reference value);
553 template <
typename InputIt,
554 typename std::enable_if<
556 InputIt>::type * =
nullptr>
557 void assign(InputIt first, InputIt last);
558 void assign(std::initializer_list<T> ilist);
561 void assign(
const std::vector<T> &other);
567 reference
at(size_type n);
568 const_reference
at(size_type n)
const;
569 const_reference
const_at(size_type n)
const;
571 const_reference
operator[](size_type n)
const;
573 const_reference
front()
const;
574 const_reference
cfront()
const;
576 const_reference
back()
const;
577 const_reference
cback()
const;
586 reverse_iterator
rbegin();
587 const_reverse_iterator
rbegin()
const noexcept;
588 const_reverse_iterator
crbegin()
const noexcept;
589 reverse_iterator
rend();
590 const_reverse_iterator
rend()
const noexcept;
591 const_reverse_iterator
crend()
const noexcept;
599 constexpr
bool empty()
const noexcept;
600 size_type
size()
const noexcept;
601 constexpr size_type
max_size()
const noexcept;
602 void reserve(size_type capacity_new);
603 size_type
capacity()
const noexcept;
612 template <
typename InputIt,
613 typename std::enable_if<
615 InputIt>::type * =
nullptr>
618 template <
class... Args>
620 template <
class... Args>
627 void resize(size_type count);
628 void resize(size_type count,
const value_type &value);
634 template <
typename... Args>
635 void construct(size_type idx, size_type count, Args &&... args);
636 template <
typename InputIt,
637 typename std::enable_if<
639 InputIt>::type * =
nullptr>
641 void insert_gap(size_type idx, size_type count);
642 void shrink(size_type size_new);
647 reference
get(size_type n);
648 const_reference
get(size_type n)
const;
649 const_reference
cget(size_type n)
const;
655 segment_vector_type _data;
659 template <
typename T,
typename Policy>
667 template <
typename T,
typename Policy>
670 template <
typename T,
typename Policy>
673 template <
typename T,
typename Policy>
676 template <
typename T,
typename Policy>
679 template <
typename T,
typename Policy>
682 template <
typename T,
typename Policy>
691 template <
typename T,
typename Policy>
693 const std::vector<T> &rhs);
694 template <
typename T,
typename Policy>
696 const std::vector<T> &rhs);
697 template <
typename T,
typename Policy>
699 template <
typename T,
typename Policy>
701 const std::vector<T> &rhs);
702 template <
typename T,
typename Policy>
704 template <
typename T,
typename Policy>
706 const std::vector<T> &rhs);
712 template <
typename T,
typename Policy>
715 template <
typename T,
typename Policy>
718 template <
typename T,
typename Policy>
720 template <
typename T,
typename Policy>
723 template <
typename T,
typename Policy>
725 template <
typename T,
typename Policy>
737 template <
typename T,
typename Policy>
764 template <
typename T,
typename Policy>
766 const value_type &value)
768 internal_reserve(count);
769 construct(0, count, value);
793 template <
typename T,
typename Policy>
796 internal_reserve(count);
826 template <
typename T,
typename Policy>
827 template <
typename InputIt,
828 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
832 internal_reserve(
static_cast<size_type
>(std::distance(first, last)));
833 construct_range(0, first, last);
857 template <
typename T,
typename Policy>
861 construct_range(0, other.
cbegin(), other.
cend());
884 template <
typename T,
typename Policy>
887 _data = std::move(other._data);
888 _segments_used = other._segments_used;
889 other._segments_used = 0;
913 template <
typename T,
typename Policy>
940 template <
typename T,
typename Policy>
963 template <
typename T,
typename Policy>
986 template <
typename T,
typename Policy>
990 assign(std::move(other));
1011 template <
typename T,
typename Policy>
1015 assign(ilist.begin(), ilist.end());
1036 template <
typename T,
typename Policy>
1066 template <
typename T,
typename Policy>
1070 if (count > max_size())
1071 throw std::length_error(
"Assignable range exceeds max size.");
1075 if (count > capacity())
1076 internal_reserve(count);
1077 else if (count < size())
1085 size_type
end = policy::get_segment(count - 1);
1086 for (size_type i = 0; i <
end; ++i)
1087 _data[i].assign(policy::segment_size(i), value);
1088 _data[
end].assign(count - policy::segment_top(
end),
1091 _segments_used =
end + 1;
1094 assert(segment_capacity_validation());
1119 template <
typename T,
typename Policy>
1120 template <
typename InputIt,
1121 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1126 size_type count =
static_cast<size_type
>(std::distance(first, last));
1127 if (count > max_size())
1128 throw std::length_error(
"Assignable range exceeds max size.");
1132 if (count > capacity())
1133 internal_reserve(count);
1134 else if (count < size())
1142 difference_type num;
1143 size_type
end = policy::get_segment(count - 1);
1144 for (size_type i = 0; i <
end; ++i) {
1145 size_type size = policy::segment_size(i);
1146 num =
static_cast<difference_type
>(size);
1147 _data[i].assign(first, std::next(first, num));
1148 std::advance(first, num);
1150 num =
static_cast<difference_type
>(
1151 std::distance(first, last));
1152 _data[
end].assign(first, std::next(first, num));
1154 _segments_used =
end + 1;
1157 assert(segment_capacity_validation());
1180 template <
typename T,
typename Policy>
1184 assign(ilist.begin(), ilist.end());
1203 template <
typename T,
typename Policy>
1226 template <
typename T,
typename Policy>
1235 _data = std::move(other._data);
1236 _segments_used = other._segments_used;
1237 other._segments_used = 0;
1257 template <
typename T,
typename Policy>
1261 assign(other.cbegin(), other.cend());
1271 template <
typename T,
typename Policy>
1294 template <
typename T,
typename Policy>
1295 typename segment_vector<T, Policy>::reference
1299 throw std::out_of_range(
"segment_vector::at");
1301 detail::conditional_add_to_tx(&
get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1316 template <
typename T,
typename Policy>
1317 typename segment_vector<T, Policy>::const_reference
1321 throw std::out_of_range(
"segment_vector::at");
1337 template <
typename T,
typename Policy>
1338 typename segment_vector<T, Policy>::const_reference
1342 throw std::out_of_range(
"segment_vector::const_at");
1357 template <
typename T,
typename Policy>
1358 typename segment_vector<T, Policy>::reference
1361 reference element =
get(n);
1363 detail::conditional_add_to_tx(&element, 1,
1364 POBJ_XADD_ASSUME_INITIALIZED);
1376 template <
typename T,
typename Policy>
1377 typename segment_vector<T, Policy>::const_reference
1391 template <
typename T,
typename Policy>
1392 typename segment_vector<T, Policy>::reference
1395 detail::conditional_add_to_tx(&_data[0][0], 1,
1396 POBJ_XADD_ASSUME_INITIALIZED);
1406 template <
typename T,
typename Policy>
1407 typename segment_vector<T, Policy>::const_reference
1420 template <
typename T,
typename Policy>
1421 typename segment_vector<T, Policy>::const_reference
1435 template <
typename T,
typename Policy>
1436 typename segment_vector<T, Policy>::reference
1439 reference element =
get(size() - 1);
1441 detail::conditional_add_to_tx(&element, 1,
1442 POBJ_XADD_ASSUME_INITIALIZED);
1452 template <
typename T,
typename Policy>
1453 typename segment_vector<T, Policy>::const_reference
1456 return get(size() - 1);
1466 template <
typename T,
typename Policy>
1467 typename segment_vector<T, Policy>::const_reference
1470 return get(size() - 1);
1478 template <
typename T,
typename Policy>
1491 template <
typename T,
typename Policy>
1506 template <
typename T,
typename Policy>
1519 template <
typename T,
typename Policy>
1532 template <
typename T,
typename Policy>
1547 template <
typename T,
typename Policy>
1560 template <
typename T,
typename Policy>
1561 typename segment_vector<T, Policy>::reverse_iterator
1564 return reverse_iterator(
end());
1573 template <
typename T,
typename Policy>
1574 typename segment_vector<T, Policy>::const_reverse_iterator
1577 return const_reverse_iterator(
end());
1588 template <
typename T,
typename Policy>
1589 typename segment_vector<T, Policy>::const_reverse_iterator
1601 template <
typename T,
typename Policy>
1602 typename segment_vector<T, Policy>::reverse_iterator
1605 return reverse_iterator(
begin());
1614 template <
typename T,
typename Policy>
1615 typename segment_vector<T, Policy>::const_reverse_iterator
1618 return const_reverse_iterator(
begin());
1629 template <
typename T,
typename Policy>
1630 typename segment_vector<T, Policy>::const_reverse_iterator
1649 template <
typename T,
typename Policy>
1653 if (start + n > size())
1654 throw std::out_of_range(
"segment_vector::range");
1656 snapshot_data(start, start + n);
1672 template <
typename T,
typename Policy>
1676 if (start + n > size())
1677 throw std::out_of_range(
"segment_vector::range");
1693 template <
typename T,
typename Policy>
1697 if (start + n > size())
1698 throw std::out_of_range(
"segment_vector::range");
1708 template <
typename T,
typename Policy>
1718 template <
typename T,
typename Policy>
1719 typename segment_vector<T, Policy>::size_type
1722 size_type result = 0;
1725 for (size_type i = 0; i < _segments_used; ++i)
1726 result += _data.const_at(i).size();
1727 }
catch (std::out_of_range &) {
1739 template <
typename T,
typename Policy>
1740 constexpr
typename segment_vector<T, Policy>::size_type
1743 return policy::max_size(_data);
1762 template <
typename T,
typename Policy>
1766 if (capacity_new <= capacity())
1777 template <
typename T,
typename Policy>
1778 typename segment_vector<T, Policy>::size_type
1781 if (_segments_used == 0)
1783 return policy::capacity(_segments_used - 1);
1797 template <
typename T,
typename Policy>
1803 size_type new_last = policy::get_segment(size() - 1);
1804 if (_segments_used - 1 == new_last)
1809 for (size_type i = new_last + 1; i < _segments_used; ++i)
1810 _data[i].free_data();
1811 _segments_used = new_last + 1;
1812 storage::resize(_data, _segments_used);
1827 template <
typename T,
typename Policy>
1833 assert(segment_capacity_validation());
1848 template <
typename T,
typename Policy>
1854 for (size_type i = 0; i < _segments_used; ++i)
1855 _data[i].free_data();
1883 template <
typename T,
typename Policy>
1887 return insert(pos, 1, value);
1913 template <
typename T,
typename Policy>
1917 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1922 get(idx) = std::move(value);
1954 template <
typename T,
typename Policy>
1959 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1963 insert_gap(idx, count);
1964 for (size_type i = idx; i < idx + count; ++i)
1965 get(i) = std::move(value);
2004 template <
typename T,
typename Policy>
2005 template <
typename InputIt,
2006 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2012 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2013 size_type gap_size =
static_cast<size_type
>(std::distance(first, last));
2017 insert_gap(idx, gap_size);
2018 for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2051 template <
typename T,
typename Policy>
2054 std::initializer_list<T> ilist)
2056 return insert(pos, ilist.begin(), ilist.end());
2087 template <
typename T,
typename Policy>
2088 template <
class... Args>
2092 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2096 detail::temp_value<value_type,
2097 noexcept(T(std::forward<Args>(args)...))>
2098 tmp(std::forward<Args>(args)...);
2100 get(idx) = std::move(tmp.get());
2130 template <
typename T,
typename Policy>
2131 template <
class... Args>
2132 typename segment_vector<T, Policy>::reference
2135 assert(size() < max_size());
2139 if (size() == capacity())
2140 internal_reserve(capacity() + 1);
2142 size_type segment = policy::get_segment(size());
2143 _data[segment].emplace_back(std::forward<Args>(args)...);
2170 template <
typename T,
typename Policy>
2174 return erase(pos, pos + 1);
2201 template <
typename T,
typename Policy>
2205 size_type count =
static_cast<size_type
>(std::distance(first, last));
2206 size_type idx =
static_cast<size_type
>(first -
cbegin());
2213 size_type _size = size();
2215 if (!std::is_trivially_destructible<T>::value ||
2216 idx + count < _size)
2217 snapshot_data(idx, _size);
2228 size_type middle = policy::get_segment(_size - count);
2229 size_type last = policy::get_segment(_size - 1);
2230 size_type middle_size = policy::index_in_segment(_size - count);
2231 for (size_type s = last; s > middle; --s)
2233 _data[middle].resize(middle_size);
2235 _segments_used = middle + 1;
2238 assert(segment_capacity_validation());
2261 template <
typename T,
typename Policy>
2265 emplace_back(value);
2286 template <
typename T,
typename Policy>
2290 emplace_back(std::move(value));
2306 template <
typename T,
typename Policy>
2315 assert(segment_capacity_validation());
2341 template <
typename T,
typename Policy>
2347 size_type _size = size();
2351 if (capacity() < count)
2352 internal_reserve(count);
2353 construct(_size, count - _size);
2356 assert(segment_capacity_validation());
2383 template <
typename T,
typename Policy>
2389 size_type _size = size();
2393 if (capacity() < count)
2394 internal_reserve(count);
2395 construct(_size, count - _size, value);
2398 assert(segment_capacity_validation());
2404 template <
typename T,
typename Policy>
2410 _data.swap(other._data);
2411 std::swap(_segments_used, other._segments_used);
2430 template <
typename T,
typename Policy>
2434 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2436 if (new_capacity > max_size())
2437 throw std::length_error(
"New capacity exceeds max size.");
2439 if (new_capacity == 0)
2442 size_type old_idx = policy::get_segment(capacity());
2443 size_type new_idx = policy::get_segment(new_capacity - 1);
2444 storage::resize(_data, new_idx + 1);
2445 for (size_type i = old_idx; i <= new_idx; ++i) {
2446 size_type segment_capacity = policy::segment_size(i);
2447 _data[i].reserve(segment_capacity);
2449 _segments_used = new_idx + 1;
2451 assert(segment_capacity_validation());
2480 template <
typename T,
typename Policy>
2481 template <
typename... Args>
2486 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2487 assert(capacity() >= size() + count);
2489 for (size_type i = idx; i < idx + count; ++i) {
2490 size_type segment = policy::get_segment(i);
2491 _data[segment].emplace_back(std::forward<Args>(args)...);
2494 assert(segment_capacity_validation());
2527 template <
typename T,
typename Policy>
2528 template <
typename InputIt,
2529 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2535 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2536 size_type count =
static_cast<size_type
>(std::distance(first, last));
2537 assert(capacity() >= size() + count);
2539 for (size_type i = idx; i < idx + count; ++i, ++first) {
2540 size_type segment = policy::get_segment(i);
2541 _data[segment].emplace_back(*first);
2544 assert(segment_capacity_validation());
2568 template <
typename T,
typename Policy>
2572 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2576 size_type _size = size();
2578 if (capacity() < _size + count)
2579 internal_reserve(_size + count);
2585 snapshot_data(idx, _size);
2587 resize(_size + count);
2588 std::move_backward(
begin,
end, dest);
2590 assert(segment_capacity_validation());
2612 template <
typename T,
typename Policy>
2616 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2617 assert(size_new <= size());
2622 if (!std::is_trivially_destructible<T>::value)
2623 snapshot_data(size_new, size());
2625 size_type
begin = policy::get_segment(size() - 1);
2626 size_type
end = policy::get_segment(size_new);
2628 _data[
begin].clear();
2630 size_type residue = policy::index_in_segment(size_new);
2633 assert(segment_capacity_validation());
2643 template <
typename T,
typename Policy>
2659 template <
typename T,
typename Policy>
2666 size_type segment = policy::get_segment(first);
2667 size_type
end = policy::get_segment(last - 1);
2668 size_type count = policy::segment_top(segment + 1) - first;
2670 while (segment !=
end) {
2671 detail::conditional_add_to_tx(&cget(first), count,
2672 POBJ_XADD_ASSUME_INITIALIZED);
2673 first = policy::segment_top(++segment);
2674 count = policy::segment_size(segment);
2676 detail::conditional_add_to_tx(&cget(first), last - first,
2677 POBJ_XADD_ASSUME_INITIALIZED);
2685 template <
typename T,
typename Policy>
2686 typename segment_vector<T, Policy>::reference
2689 size_type s_idx = policy::get_segment(n);
2690 size_type local_idx = policy::index_in_segment(n);
2692 return _data[s_idx][local_idx];
2700 template <
typename T,
typename Policy>
2701 typename segment_vector<T, Policy>::const_reference
2704 size_type s_idx = policy::get_segment(n);
2705 size_type local_idx = policy::index_in_segment(n);
2707 return _data[s_idx][local_idx];
2715 template <
typename T,
typename Policy>
2716 typename segment_vector<T, Policy>::const_reference
2719 size_type s_idx = policy::get_segment(n);
2720 size_type local_idx = policy::index_in_segment(n);
2722 return _data[s_idx][local_idx];
2732 template <
typename T,
typename Policy>
2736 for (size_type i = 0; i < _segments_used; ++i)
2737 if (_data.const_at(i).capacity() != policy::segment_size(i))
2748 template <
typename T,
typename Policy>
2769 template <
typename T,
typename Policy>
2793 template <
typename T,
typename Policy>
2798 return !(lhs == rhs);
2813 template <
typename T,
typename Policy>
2818 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2834 template <
typename T,
typename Policy>
2839 return !(rhs < lhs);
2854 template <
typename T,
typename Policy>
2874 template <
typename T,
typename Policy>
2879 return !(lhs < rhs);
2895 template <
typename T,
typename Policy>
2899 return lhs.
size() == rhs.size() &&
2900 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2916 template <
typename T,
typename Policy>
2920 return !(lhs == rhs);
2934 template <
typename T,
typename Policy>
2938 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2953 template <
typename T,
typename Policy>
2957 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2973 template <
typename T,
typename Policy>
2977 return !(lhs <= rhs);
2991 template <
typename T,
typename Policy>
2995 return !(lhs < rhs);
3011 template <
typename T,
typename Policy>
3031 template <
typename T,
typename Policy>
3035 return !(lhs == rhs);
3049 template <
typename T,
typename Policy>
3067 template <
typename T,
typename Policy>
3071 return !(rhs < lhs);
3086 template <
typename T,
typename Policy>
3104 template <
typename T,
typename Policy>
3108 return !(lhs < rhs);