38 #ifndef LIBPMEMOBJ_SEGMENT_VECTOR_HPP
39 #define LIBPMEMOBJ_SEGMENT_VECTOR_HPP
60 namespace segment_vector_internal
69 template <
typename Container,
bool is_const>
73 using iterator_category = std::random_access_iterator_tag;
74 using difference_type = std::ptrdiff_t;
75 using table_type = Container;
76 using size_type =
typename table_type::size_type;
77 using value_type =
typename table_type::value_type;
80 typename std::conditional<is_const,
const table_type *,
83 typename std::conditional<is_const,
84 typename table_type::const_reference,
85 typename table_type::reference>::type;
87 typename std::conditional<is_const,
88 typename table_type::const_pointer,
89 typename table_type::pointer>::type;
109 template <
typename U = void,
110 typename =
typename std::enable_if<is_const, U>::type>
155 template <
typename Container,
bool is_const>
157 : table(
nullptr), index()
165 template <
typename Container,
bool is_const>
167 size_type idx) noexcept
168 : table(tab), index(idx)
176 template <
typename Container,
bool is_const>
179 : table(other.table), index(other.index)
184 template <
typename Container,
bool is_const>
185 template <
typename U,
typename>
188 : table(other.table), index(other.index)
197 template <
typename Container,
bool is_const>
210 template <
typename Container,
bool is_const>
214 auto iterator = *
this;
224 template <
typename Container,
bool is_const>
236 template <
typename Container,
bool is_const>
240 index +=
static_cast<size_type
>(idx);
249 template <
typename Container,
bool is_const>
262 template <
typename Container,
bool is_const>
266 auto iterator = *
this;
276 template <
typename Container,
bool is_const>
288 template <
typename Container,
bool is_const>
292 index -=
static_cast<size_type
>(idx);
301 template <
typename Container,
bool is_const>
303 typename segment_iterator<Container, is_const>::difference_type
307 return static_cast<difference_type
>(index + rhs.index);
315 template <
typename Container,
bool is_const>
317 typename segment_iterator<Container, is_const>::difference_type
321 return static_cast<difference_type
>(index - rhs.index);
331 template <
typename Container,
bool is_const>
337 return (table == rhs.table) && (index == rhs.index);
348 template <
typename Container,
bool is_const>
354 return (table != rhs.table) || (index != rhs.index);
367 template <
typename Container,
bool is_const>
373 if (table != rhs.table)
374 throw std::invalid_argument(
"segment_iterator::operator<");
376 return index < rhs.index;
390 template <
typename Container,
bool is_const>
396 if (table != rhs.table)
397 throw std::invalid_argument(
"segment_iterator::operator<");
399 return index > rhs.index;
413 template <
typename Container,
bool is_const>
419 if (table != rhs.table)
420 throw std::invalid_argument(
"segment_iterator::operator<");
422 return index <= rhs.index;
436 template <
typename Container,
bool is_const>
442 if (table != rhs.table)
443 throw std::invalid_argument(
"segment_iterator::operator<");
445 return index >= rhs.index;
451 template <
typename Container,
bool is_const>
452 typename segment_iterator<Container, is_const>::reference
455 return table->operator[](index);
461 template <
typename Container,
bool is_const>
462 typename segment_iterator<Container, is_const>::pointer
480 segment_vector_internal::exponential_size_policy<
491 template <
size_t SegmentSize = 1024,
495 SegmentType, SegmentSize>;
525 template <
typename T,
typename Policy = exponential_size_vector_policy<>>
529 using policy_type = Policy;
530 using segment_type =
typename policy_type::template segment_type<T>;
531 using segment_vector_type =
532 typename policy_type::template segment_vector_type<T>;
534 using policy = policy_type;
535 using storage = policy_type;
538 using value_type = T;
539 using size_type = std::size_t;
540 using difference_type = std::ptrdiff_t;
541 using reference = value_type &;
542 using const_reference =
const value_type &;
543 using pointer = value_type *;
544 using const_pointer =
const value_type *;
550 using reverse_iterator = std::reverse_iterator<iterator>;
551 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
557 template <
typename InputIt,
558 typename std::enable_if<
560 InputIt>::type * =
nullptr>
574 void assign(size_type count, const_reference value);
575 template <
typename InputIt,
576 typename std::enable_if<
578 InputIt>::type * =
nullptr>
579 void assign(InputIt first, InputIt last);
580 void assign(std::initializer_list<T> ilist);
583 void assign(
const std::vector<T> &other);
589 reference
at(size_type n);
590 const_reference
at(size_type n)
const;
591 const_reference
const_at(size_type n)
const;
593 const_reference
operator[](size_type n)
const;
595 const_reference
front()
const;
596 const_reference
cfront()
const;
598 const_reference
back()
const;
599 const_reference
cback()
const;
608 reverse_iterator
rbegin();
609 const_reverse_iterator
rbegin()
const noexcept;
610 const_reverse_iterator
crbegin()
const noexcept;
611 reverse_iterator
rend();
612 const_reverse_iterator
rend()
const noexcept;
613 const_reverse_iterator
crend()
const noexcept;
621 constexpr
bool empty()
const noexcept;
622 size_type
size()
const noexcept;
623 constexpr size_type
max_size()
const noexcept;
624 void reserve(size_type capacity_new);
625 size_type
capacity()
const noexcept;
634 template <
typename InputIt,
635 typename std::enable_if<
637 InputIt>::type * =
nullptr>
640 template <
class... Args>
642 template <
class... Args>
649 void resize(size_type count);
650 void resize(size_type count,
const value_type &value);
656 template <
typename... Args>
657 void construct(size_type idx, size_type count, Args &&... args);
658 template <
typename InputIt,
659 typename std::enable_if<
661 InputIt>::type * =
nullptr>
663 void insert_gap(size_type idx, size_type count);
664 void shrink(size_type size_new);
669 reference
get(size_type n);
670 const_reference
get(size_type n)
const;
671 const_reference
cget(size_type n)
const;
677 segment_vector_type _data;
681 template <
typename T,
typename Policy>
689 template <
typename T,
typename Policy>
692 template <
typename T,
typename Policy>
695 template <
typename T,
typename Policy>
698 template <
typename T,
typename Policy>
701 template <
typename T,
typename Policy>
704 template <
typename T,
typename Policy>
713 template <
typename T,
typename Policy>
715 const std::vector<T> &rhs);
716 template <
typename T,
typename Policy>
718 const std::vector<T> &rhs);
719 template <
typename T,
typename Policy>
721 template <
typename T,
typename Policy>
723 const std::vector<T> &rhs);
724 template <
typename T,
typename Policy>
726 template <
typename T,
typename Policy>
728 const std::vector<T> &rhs);
734 template <
typename T,
typename Policy>
737 template <
typename T,
typename Policy>
740 template <
typename T,
typename Policy>
742 template <
typename T,
typename Policy>
745 template <
typename T,
typename Policy>
747 template <
typename T,
typename Policy>
759 template <
typename T,
typename Policy>
786 template <
typename T,
typename Policy>
788 const value_type &value)
790 internal_reserve(count);
791 construct(0, count, value);
815 template <
typename T,
typename Policy>
818 internal_reserve(count);
848 template <
typename T,
typename Policy>
849 template <
typename InputIt,
850 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
854 internal_reserve(
static_cast<size_type
>(std::distance(first, last)));
855 construct_range(0, first, last);
879 template <
typename T,
typename Policy>
883 construct_range(0, other.
cbegin(), other.
cend());
906 template <
typename T,
typename Policy>
909 _data = std::move(other._data);
910 _segments_used = other._segments_used;
911 other._segments_used = 0;
935 template <
typename T,
typename Policy>
962 template <
typename T,
typename Policy>
985 template <
typename T,
typename Policy>
1008 template <
typename T,
typename Policy>
1012 assign(std::move(other));
1033 template <
typename T,
typename Policy>
1037 assign(ilist.begin(), ilist.end());
1058 template <
typename T,
typename Policy>
1088 template <
typename T,
typename Policy>
1092 if (count > max_size())
1093 throw std::length_error(
"Assignable range exceeds max size.");
1097 if (count > capacity())
1098 internal_reserve(count);
1099 else if (count < size())
1107 size_type
end = policy::get_segment(count - 1);
1108 for (size_type i = 0; i <
end; ++i)
1109 _data[i].assign(policy::segment_size(i), value);
1110 _data[
end].assign(count - policy::segment_top(
end),
1113 _segments_used =
end + 1;
1116 assert(segment_capacity_validation());
1141 template <
typename T,
typename Policy>
1142 template <
typename InputIt,
1143 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1148 size_type count =
static_cast<size_type
>(std::distance(first, last));
1149 if (count > max_size())
1150 throw std::length_error(
"Assignable range exceeds max size.");
1154 if (count > capacity())
1155 internal_reserve(count);
1156 else if (count < size())
1164 difference_type num;
1165 size_type
end = policy::get_segment(count - 1);
1166 for (size_type i = 0; i <
end; ++i) {
1167 size_type size = policy::segment_size(i);
1168 num =
static_cast<difference_type
>(size);
1169 _data[i].assign(first, std::next(first, num));
1170 std::advance(first, num);
1172 num =
static_cast<difference_type
>(
1173 std::distance(first, last));
1174 _data[
end].assign(first, std::next(first, num));
1176 _segments_used =
end + 1;
1179 assert(segment_capacity_validation());
1202 template <
typename T,
typename Policy>
1206 assign(ilist.begin(), ilist.end());
1225 template <
typename T,
typename Policy>
1248 template <
typename T,
typename Policy>
1257 _data = std::move(other._data);
1258 _segments_used = other._segments_used;
1259 other._segments_used = 0;
1279 template <
typename T,
typename Policy>
1283 assign(other.cbegin(), other.cend());
1297 template <
typename T,
typename Policy>
1316 template <
typename T,
typename Policy>
1317 typename segment_vector<T, Policy>::reference
1321 throw std::out_of_range(
"segment_vector::at");
1323 detail::conditional_add_to_tx(&
get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1338 template <
typename T,
typename Policy>
1339 typename segment_vector<T, Policy>::const_reference
1343 throw std::out_of_range(
"segment_vector::at");
1359 template <
typename T,
typename Policy>
1360 typename segment_vector<T, Policy>::const_reference
1364 throw std::out_of_range(
"segment_vector::const_at");
1379 template <
typename T,
typename Policy>
1380 typename segment_vector<T, Policy>::reference
1383 reference element =
get(n);
1385 detail::conditional_add_to_tx(&element, 1,
1386 POBJ_XADD_ASSUME_INITIALIZED);
1398 template <
typename T,
typename Policy>
1399 typename segment_vector<T, Policy>::const_reference
1413 template <
typename T,
typename Policy>
1414 typename segment_vector<T, Policy>::reference
1417 detail::conditional_add_to_tx(&_data[0][0], 1,
1418 POBJ_XADD_ASSUME_INITIALIZED);
1428 template <
typename T,
typename Policy>
1429 typename segment_vector<T, Policy>::const_reference
1442 template <
typename T,
typename Policy>
1443 typename segment_vector<T, Policy>::const_reference
1457 template <
typename T,
typename Policy>
1458 typename segment_vector<T, Policy>::reference
1461 reference element =
get(size() - 1);
1463 detail::conditional_add_to_tx(&element, 1,
1464 POBJ_XADD_ASSUME_INITIALIZED);
1474 template <
typename T,
typename Policy>
1475 typename segment_vector<T, Policy>::const_reference
1478 return get(size() - 1);
1488 template <
typename T,
typename Policy>
1489 typename segment_vector<T, Policy>::const_reference
1492 return get(size() - 1);
1500 template <
typename T,
typename Policy>
1513 template <
typename T,
typename Policy>
1528 template <
typename T,
typename Policy>
1541 template <
typename T,
typename Policy>
1554 template <
typename T,
typename Policy>
1569 template <
typename T,
typename Policy>
1582 template <
typename T,
typename Policy>
1583 typename segment_vector<T, Policy>::reverse_iterator
1586 return reverse_iterator(
end());
1595 template <
typename T,
typename Policy>
1596 typename segment_vector<T, Policy>::const_reverse_iterator
1599 return const_reverse_iterator(
end());
1610 template <
typename T,
typename Policy>
1611 typename segment_vector<T, Policy>::const_reverse_iterator
1623 template <
typename T,
typename Policy>
1624 typename segment_vector<T, Policy>::reverse_iterator
1627 return reverse_iterator(
begin());
1636 template <
typename T,
typename Policy>
1637 typename segment_vector<T, Policy>::const_reverse_iterator
1640 return const_reverse_iterator(
begin());
1651 template <
typename T,
typename Policy>
1652 typename segment_vector<T, Policy>::const_reverse_iterator
1671 template <
typename T,
typename Policy>
1675 if (start + n > size())
1676 throw std::out_of_range(
"segment_vector::range");
1678 snapshot_data(start, start + n);
1694 template <
typename T,
typename Policy>
1698 if (start + n > size())
1699 throw std::out_of_range(
"segment_vector::range");
1715 template <
typename T,
typename Policy>
1719 if (start + n > size())
1720 throw std::out_of_range(
"segment_vector::range");
1730 template <
typename T,
typename Policy>
1740 template <
typename T,
typename Policy>
1741 typename segment_vector<T, Policy>::size_type
1744 size_type result = 0;
1747 for (size_type i = 0; i < _segments_used; ++i)
1748 result += _data.const_at(i).size();
1749 }
catch (std::out_of_range &) {
1761 template <
typename T,
typename Policy>
1762 constexpr
typename segment_vector<T, Policy>::size_type
1765 return policy::max_size(_data);
1784 template <
typename T,
typename Policy>
1788 if (capacity_new <= capacity())
1799 template <
typename T,
typename Policy>
1800 typename segment_vector<T, Policy>::size_type
1803 if (_segments_used == 0)
1805 return policy::capacity(_segments_used - 1);
1819 template <
typename T,
typename Policy>
1825 size_type new_last = policy::get_segment(size() - 1);
1826 if (_segments_used - 1 == new_last)
1831 for (size_type i = new_last + 1; i < _segments_used; ++i)
1832 _data[i].free_data();
1833 _segments_used = new_last + 1;
1834 storage::resize(_data, _segments_used);
1849 template <
typename T,
typename Policy>
1855 assert(segment_capacity_validation());
1870 template <
typename T,
typename Policy>
1876 for (size_type i = 0; i < _segments_used; ++i)
1877 _data[i].free_data();
1905 template <
typename T,
typename Policy>
1909 return insert(pos, 1, value);
1935 template <
typename T,
typename Policy>
1939 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1944 get(idx) = std::move(value);
1976 template <
typename T,
typename Policy>
1981 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1985 insert_gap(idx, count);
1986 for (size_type i = idx; i < idx + count; ++i)
1987 get(i) = std::move(value);
2026 template <
typename T,
typename Policy>
2027 template <
typename InputIt,
2028 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2034 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2035 size_type gap_size =
static_cast<size_type
>(std::distance(first, last));
2039 insert_gap(idx, gap_size);
2040 for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2073 template <
typename T,
typename Policy>
2076 std::initializer_list<T> ilist)
2078 return insert(pos, ilist.begin(), ilist.end());
2109 template <
typename T,
typename Policy>
2110 template <
class... Args>
2114 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2119 noexcept(T(std::forward<Args>(args)...))>
2120 tmp(std::forward<Args>(args)...);
2122 get(idx) = std::move(tmp.get());
2152 template <
typename T,
typename Policy>
2153 template <
class... Args>
2154 typename segment_vector<T, Policy>::reference
2157 assert(size() < max_size());
2161 if (size() == capacity())
2162 internal_reserve(capacity() + 1);
2164 size_type segment = policy::get_segment(size());
2165 _data[segment].emplace_back(std::forward<Args>(args)...);
2192 template <
typename T,
typename Policy>
2196 return erase(pos, pos + 1);
2223 template <
typename T,
typename Policy>
2227 size_type count =
static_cast<size_type
>(std::distance(first, last));
2228 size_type idx =
static_cast<size_type
>(first -
cbegin());
2235 size_type _size = size();
2237 snapshot_data(idx, _size);
2248 size_type middle = policy::get_segment(_size - count);
2249 size_type last = policy::get_segment(_size - 1);
2250 size_type middle_size = policy::index_in_segment(_size - count);
2251 for (size_type s = last; s > middle; --s)
2253 _data[middle].resize(middle_size);
2255 _segments_used = middle + 1;
2258 assert(segment_capacity_validation());
2281 template <
typename T,
typename Policy>
2285 emplace_back(value);
2306 template <
typename T,
typename Policy>
2310 emplace_back(std::move(value));
2326 template <
typename T,
typename Policy>
2335 assert(segment_capacity_validation());
2361 template <
typename T,
typename Policy>
2367 size_type _size = size();
2371 if (capacity() < count)
2372 internal_reserve(count);
2373 construct(_size, count - _size);
2376 assert(segment_capacity_validation());
2403 template <
typename T,
typename Policy>
2409 size_type _size = size();
2413 if (capacity() < count)
2414 internal_reserve(count);
2415 construct(_size, count - _size, value);
2418 assert(segment_capacity_validation());
2424 template <
typename T,
typename Policy>
2430 _data.swap(other._data);
2431 std::swap(_segments_used, other._segments_used);
2450 template <
typename T,
typename Policy>
2454 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2456 if (new_capacity > max_size())
2457 throw std::length_error(
"New capacity exceeds max size.");
2459 if (new_capacity == 0)
2462 size_type old_idx = policy::get_segment(capacity());
2463 size_type new_idx = policy::get_segment(new_capacity - 1);
2464 storage::resize(_data, new_idx + 1);
2465 for (size_type i = old_idx; i <= new_idx; ++i) {
2466 size_type segment_capacity = policy::segment_size(i);
2467 _data[i].reserve(segment_capacity);
2469 _segments_used = new_idx + 1;
2471 assert(segment_capacity_validation());
2500 template <
typename T,
typename Policy>
2501 template <
typename... Args>
2506 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2507 assert(capacity() >= size() + count);
2509 for (size_type i = idx; i < idx + count; ++i) {
2510 size_type segment = policy::get_segment(i);
2511 _data[segment].emplace_back(std::forward<Args>(args)...);
2514 assert(segment_capacity_validation());
2547 template <
typename T,
typename Policy>
2548 template <
typename InputIt,
2549 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2555 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2556 size_type count =
static_cast<size_type
>(std::distance(first, last));
2557 assert(capacity() >= size() + count);
2559 for (size_type i = idx; i < idx + count; ++i, ++first) {
2560 size_type segment = policy::get_segment(i);
2561 _data[segment].emplace_back(*first);
2564 assert(segment_capacity_validation());
2588 template <
typename T,
typename Policy>
2592 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2596 size_type _size = size();
2598 if (capacity() < _size + count)
2599 internal_reserve(_size + count);
2605 snapshot_data(idx, _size);
2607 resize(_size + count);
2608 std::move_backward(
begin,
end, dest);
2610 assert(segment_capacity_validation());
2632 template <
typename T,
typename Policy>
2636 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2637 assert(size_new <= size());
2642 snapshot_data(size_new, size());
2644 size_type
begin = policy::get_segment(size() - 1);
2645 size_type
end = policy::get_segment(size_new);
2647 _data[
begin].clear();
2649 size_type residue = policy::index_in_segment(size_new);
2652 assert(segment_capacity_validation());
2662 template <
typename T,
typename Policy>
2666 auto pop = pmemobj_pool_by_ptr(
this);
2667 assert(pop !=
nullptr);
2680 template <
typename T,
typename Policy>
2687 size_type segment = policy::get_segment(first);
2688 size_type
end = policy::get_segment(last - 1);
2689 size_type count = policy::segment_top(segment + 1) - first;
2691 while (segment !=
end) {
2692 detail::conditional_add_to_tx(&cget(first), count,
2693 POBJ_XADD_ASSUME_INITIALIZED);
2694 first = policy::segment_top(++segment);
2695 count = policy::segment_size(segment);
2697 detail::conditional_add_to_tx(&cget(first), last - first,
2698 POBJ_XADD_ASSUME_INITIALIZED);
2706 template <
typename T,
typename Policy>
2707 typename segment_vector<T, Policy>::reference
2710 size_type s_idx = policy::get_segment(n);
2711 size_type local_idx = policy::index_in_segment(n);
2713 return _data[s_idx][local_idx];
2721 template <
typename T,
typename Policy>
2722 typename segment_vector<T, Policy>::const_reference
2725 size_type s_idx = policy::get_segment(n);
2726 size_type local_idx = policy::index_in_segment(n);
2728 return _data[s_idx][local_idx];
2736 template <
typename T,
typename Policy>
2737 typename segment_vector<T, Policy>::const_reference
2740 size_type s_idx = policy::get_segment(n);
2741 size_type local_idx = policy::index_in_segment(n);
2743 return _data[s_idx][local_idx];
2753 template <
typename T,
typename Policy>
2757 for (size_type i = 0; i < _segments_used; ++i)
2758 if (_data.const_at(i).capacity() != policy::segment_size(i))
2769 template <
typename T,
typename Policy>
2790 template <
typename T,
typename Policy>
2814 template <
typename T,
typename Policy>
2819 return !(lhs == rhs);
2834 template <
typename T,
typename Policy>
2839 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2855 template <
typename T,
typename Policy>
2860 return !(rhs < lhs);
2875 template <
typename T,
typename Policy>
2895 template <
typename T,
typename Policy>
2900 return !(lhs < rhs);
2916 template <
typename T,
typename Policy>
2920 return lhs.
size() == rhs.size() &&
2921 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2937 template <
typename T,
typename Policy>
2941 return !(lhs == rhs);
2955 template <
typename T,
typename Policy>
2959 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2974 template <
typename T,
typename Policy>
2978 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2994 template <
typename T,
typename Policy>
2998 return !(lhs <= rhs);
3012 template <
typename T,
typename Policy>
3016 return !(lhs < rhs);
3032 template <
typename T,
typename Policy>
3052 template <
typename T,
typename Policy>
3056 return !(lhs == rhs);
3070 template <
typename T,
typename Policy>
3088 template <
typename T,
typename Policy>
3092 return !(rhs < lhs);
3107 template <
typename T,
typename Policy>
3125 template <
typename T,
typename Policy>
3129 return !(lhs < rhs);