9 #ifndef LIBPMEMOBJ_SEGMENT_VECTOR_HPP
10 #define LIBPMEMOBJ_SEGMENT_VECTOR_HPP
31 namespace segment_vector_internal
40 template <
typename Container,
bool is_const>
44 using iterator_category = std::random_access_iterator_tag;
45 using difference_type = std::ptrdiff_t;
46 using table_type = Container;
47 using size_type =
typename table_type::size_type;
48 using value_type =
typename table_type::value_type;
51 typename std::conditional<is_const,
const table_type *,
54 typename std::conditional<is_const,
55 typename table_type::const_reference,
56 typename table_type::reference>::type;
58 typename std::conditional<is_const,
59 typename table_type::const_pointer,
60 typename table_type::pointer>::type;
80 template <
typename U = void,
81 typename =
typename std::enable_if<is_const, U>::type>
126 template <
typename Container,
bool is_const>
128 : table(
nullptr), index()
136 template <
typename Container,
bool is_const>
138 size_type idx) noexcept
139 : table(tab), index(idx)
147 template <
typename Container,
bool is_const>
150 : table(other.table), index(other.index)
155 template <
typename Container,
bool is_const>
156 template <
typename U,
typename>
159 : table(other.table), index(other.index)
168 template <
typename Container,
bool is_const>
181 template <
typename Container,
bool is_const>
185 auto iterator = *
this;
195 template <
typename Container,
bool is_const>
207 template <
typename Container,
bool is_const>
211 index +=
static_cast<size_type
>(idx);
220 template <
typename Container,
bool is_const>
233 template <
typename Container,
bool is_const>
237 auto iterator = *
this;
247 template <
typename Container,
bool is_const>
259 template <
typename Container,
bool is_const>
263 index -=
static_cast<size_type
>(idx);
272 template <
typename Container,
bool is_const>
274 typename segment_iterator<Container, is_const>::difference_type
278 return static_cast<difference_type
>(index + rhs.index);
286 template <
typename Container,
bool is_const>
288 typename segment_iterator<Container, is_const>::difference_type
292 return static_cast<difference_type
>(index - rhs.index);
302 template <
typename Container,
bool is_const>
308 return (table == rhs.table) && (index == rhs.index);
319 template <
typename Container,
bool is_const>
325 return (table != rhs.table) || (index != rhs.index);
338 template <
typename Container,
bool is_const>
344 if (table != rhs.table)
345 throw std::invalid_argument(
"segment_iterator::operator<");
347 return index < rhs.index;
361 template <
typename Container,
bool is_const>
367 if (table != rhs.table)
368 throw std::invalid_argument(
"segment_iterator::operator<");
370 return index > rhs.index;
384 template <
typename Container,
bool is_const>
390 if (table != rhs.table)
391 throw std::invalid_argument(
"segment_iterator::operator<");
393 return index <= rhs.index;
407 template <
typename Container,
bool is_const>
413 if (table != rhs.table)
414 throw std::invalid_argument(
"segment_iterator::operator<");
416 return index >= rhs.index;
422 template <
typename Container,
bool is_const>
423 typename segment_iterator<Container, is_const>::reference
426 return table->operator[](index);
432 template <
typename Container,
bool is_const>
433 typename segment_iterator<Container, is_const>::pointer
451 segment_vector_internal::exponential_size_policy<
462 template <
size_t SegmentSize = 1024,
466 SegmentType, SegmentSize>;
496 template <
typename T,
typename Policy = exponential_size_vector_policy<>>
500 using policy_type = Policy;
501 using segment_type =
typename policy_type::template segment_type<T>;
502 using segment_vector_type =
503 typename policy_type::template segment_vector_type<T>;
505 using policy = policy_type;
506 using storage = policy_type;
509 using value_type = T;
510 using size_type = std::size_t;
511 using difference_type = std::ptrdiff_t;
512 using reference = value_type &;
513 using const_reference =
const value_type &;
514 using pointer = value_type *;
515 using const_pointer =
const value_type *;
521 using reverse_iterator = std::reverse_iterator<iterator>;
522 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
528 template <
typename InputIt,
529 typename std::enable_if<
531 InputIt>::type * =
nullptr>
545 void assign(size_type count, const_reference value);
546 template <
typename InputIt,
547 typename std::enable_if<
549 InputIt>::type * =
nullptr>
550 void assign(InputIt first, InputIt last);
551 void assign(std::initializer_list<T> ilist);
554 void assign(
const std::vector<T> &other);
560 reference
at(size_type n);
561 const_reference
at(size_type n)
const;
562 const_reference
const_at(size_type n)
const;
564 const_reference
operator[](size_type n)
const;
566 const_reference
front()
const;
567 const_reference
cfront()
const;
569 const_reference
back()
const;
570 const_reference
cback()
const;
579 reverse_iterator
rbegin();
580 const_reverse_iterator
rbegin()
const noexcept;
581 const_reverse_iterator
crbegin()
const noexcept;
582 reverse_iterator
rend();
583 const_reverse_iterator
rend()
const noexcept;
584 const_reverse_iterator
crend()
const noexcept;
592 constexpr
bool empty()
const noexcept;
593 size_type
size()
const noexcept;
594 constexpr size_type
max_size()
const noexcept;
595 void reserve(size_type capacity_new);
596 size_type
capacity()
const noexcept;
605 template <
typename InputIt,
606 typename std::enable_if<
608 InputIt>::type * =
nullptr>
611 template <
class... Args>
613 template <
class... Args>
620 void resize(size_type count);
621 void resize(size_type count,
const value_type &value);
627 template <
typename... Args>
628 void construct(size_type idx, size_type count, Args &&... args);
629 template <
typename InputIt,
630 typename std::enable_if<
632 InputIt>::type * =
nullptr>
634 void insert_gap(size_type idx, size_type count);
635 void shrink(size_type size_new);
640 reference
get(size_type n);
641 const_reference
get(size_type n)
const;
642 const_reference
cget(size_type n)
const;
648 segment_vector_type _data;
652 template <
typename T,
typename Policy>
660 template <
typename T,
typename Policy>
663 template <
typename T,
typename Policy>
666 template <
typename T,
typename Policy>
669 template <
typename T,
typename Policy>
672 template <
typename T,
typename Policy>
675 template <
typename T,
typename Policy>
684 template <
typename T,
typename Policy>
686 const std::vector<T> &rhs);
687 template <
typename T,
typename Policy>
689 const std::vector<T> &rhs);
690 template <
typename T,
typename Policy>
692 template <
typename T,
typename Policy>
694 const std::vector<T> &rhs);
695 template <
typename T,
typename Policy>
697 template <
typename T,
typename Policy>
699 const std::vector<T> &rhs);
705 template <
typename T,
typename Policy>
708 template <
typename T,
typename Policy>
711 template <
typename T,
typename Policy>
713 template <
typename T,
typename Policy>
716 template <
typename T,
typename Policy>
718 template <
typename T,
typename Policy>
730 template <
typename T,
typename Policy>
757 template <
typename T,
typename Policy>
759 const value_type &value)
761 internal_reserve(count);
762 construct(0, count, value);
786 template <
typename T,
typename Policy>
789 internal_reserve(count);
819 template <
typename T,
typename Policy>
820 template <
typename InputIt,
821 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
825 internal_reserve(
static_cast<size_type
>(std::distance(first, last)));
826 construct_range(0, first, last);
850 template <
typename T,
typename Policy>
854 construct_range(0, other.
cbegin(), other.
cend());
877 template <
typename T,
typename Policy>
880 _data = std::move(other._data);
881 _segments_used = other._segments_used;
882 other._segments_used = 0;
906 template <
typename T,
typename Policy>
933 template <
typename T,
typename Policy>
956 template <
typename T,
typename Policy>
979 template <
typename T,
typename Policy>
983 assign(std::move(other));
1004 template <
typename T,
typename Policy>
1008 assign(ilist.begin(), ilist.end());
1029 template <
typename T,
typename Policy>
1059 template <
typename T,
typename Policy>
1063 if (count > max_size())
1064 throw std::length_error(
"Assignable range exceeds max size.");
1068 if (count > capacity())
1069 internal_reserve(count);
1070 else if (count < size())
1078 size_type
end = policy::get_segment(count - 1);
1079 for (size_type i = 0; i <
end; ++i)
1080 _data[i].assign(policy::segment_size(i), value);
1081 _data[
end].assign(count - policy::segment_top(
end),
1084 _segments_used =
end + 1;
1087 assert(segment_capacity_validation());
1112 template <
typename T,
typename Policy>
1113 template <
typename InputIt,
1114 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
1119 size_type count =
static_cast<size_type
>(std::distance(first, last));
1120 if (count > max_size())
1121 throw std::length_error(
"Assignable range exceeds max size.");
1125 if (count > capacity())
1126 internal_reserve(count);
1127 else if (count < size())
1135 difference_type num;
1136 size_type
end = policy::get_segment(count - 1);
1137 for (size_type i = 0; i <
end; ++i) {
1138 size_type size = policy::segment_size(i);
1139 num =
static_cast<difference_type
>(size);
1140 _data[i].assign(first, std::next(first, num));
1141 std::advance(first, num);
1143 num =
static_cast<difference_type
>(
1144 std::distance(first, last));
1145 _data[
end].assign(first, std::next(first, num));
1147 _segments_used =
end + 1;
1150 assert(segment_capacity_validation());
1173 template <
typename T,
typename Policy>
1177 assign(ilist.begin(), ilist.end());
1196 template <
typename T,
typename Policy>
1219 template <
typename T,
typename Policy>
1228 _data = std::move(other._data);
1229 _segments_used = other._segments_used;
1230 other._segments_used = 0;
1250 template <
typename T,
typename Policy>
1254 assign(other.cbegin(), other.cend());
1264 template <
typename T,
typename Policy>
1287 template <
typename T,
typename Policy>
1288 typename segment_vector<T, Policy>::reference
1292 throw std::out_of_range(
"segment_vector::at");
1294 detail::conditional_add_to_tx(&
get(n), 1, POBJ_XADD_ASSUME_INITIALIZED);
1309 template <
typename T,
typename Policy>
1310 typename segment_vector<T, Policy>::const_reference
1314 throw std::out_of_range(
"segment_vector::at");
1330 template <
typename T,
typename Policy>
1331 typename segment_vector<T, Policy>::const_reference
1335 throw std::out_of_range(
"segment_vector::const_at");
1350 template <
typename T,
typename Policy>
1351 typename segment_vector<T, Policy>::reference
1354 reference element =
get(n);
1356 detail::conditional_add_to_tx(&element, 1,
1357 POBJ_XADD_ASSUME_INITIALIZED);
1369 template <
typename T,
typename Policy>
1370 typename segment_vector<T, Policy>::const_reference
1384 template <
typename T,
typename Policy>
1385 typename segment_vector<T, Policy>::reference
1388 detail::conditional_add_to_tx(&_data[0][0], 1,
1389 POBJ_XADD_ASSUME_INITIALIZED);
1399 template <
typename T,
typename Policy>
1400 typename segment_vector<T, Policy>::const_reference
1413 template <
typename T,
typename Policy>
1414 typename segment_vector<T, Policy>::const_reference
1428 template <
typename T,
typename Policy>
1429 typename segment_vector<T, Policy>::reference
1432 reference element =
get(size() - 1);
1434 detail::conditional_add_to_tx(&element, 1,
1435 POBJ_XADD_ASSUME_INITIALIZED);
1445 template <
typename T,
typename Policy>
1446 typename segment_vector<T, Policy>::const_reference
1449 return get(size() - 1);
1459 template <
typename T,
typename Policy>
1460 typename segment_vector<T, Policy>::const_reference
1463 return get(size() - 1);
1471 template <
typename T,
typename Policy>
1484 template <
typename T,
typename Policy>
1499 template <
typename T,
typename Policy>
1512 template <
typename T,
typename Policy>
1525 template <
typename T,
typename Policy>
1540 template <
typename T,
typename Policy>
1553 template <
typename T,
typename Policy>
1554 typename segment_vector<T, Policy>::reverse_iterator
1557 return reverse_iterator(
end());
1566 template <
typename T,
typename Policy>
1567 typename segment_vector<T, Policy>::const_reverse_iterator
1570 return const_reverse_iterator(
end());
1581 template <
typename T,
typename Policy>
1582 typename segment_vector<T, Policy>::const_reverse_iterator
1594 template <
typename T,
typename Policy>
1595 typename segment_vector<T, Policy>::reverse_iterator
1598 return reverse_iterator(
begin());
1607 template <
typename T,
typename Policy>
1608 typename segment_vector<T, Policy>::const_reverse_iterator
1611 return const_reverse_iterator(
begin());
1622 template <
typename T,
typename Policy>
1623 typename segment_vector<T, Policy>::const_reverse_iterator
1642 template <
typename T,
typename Policy>
1646 if (start + n > size())
1647 throw std::out_of_range(
"segment_vector::range");
1649 snapshot_data(start, start + n);
1665 template <
typename T,
typename Policy>
1669 if (start + n > size())
1670 throw std::out_of_range(
"segment_vector::range");
1686 template <
typename T,
typename Policy>
1690 if (start + n > size())
1691 throw std::out_of_range(
"segment_vector::range");
1701 template <
typename T,
typename Policy>
1711 template <
typename T,
typename Policy>
1712 typename segment_vector<T, Policy>::size_type
1715 size_type result = 0;
1718 for (size_type i = 0; i < _segments_used; ++i)
1719 result += _data.const_at(i).size();
1720 }
catch (std::out_of_range &) {
1732 template <
typename T,
typename Policy>
1733 constexpr
typename segment_vector<T, Policy>::size_type
1736 return policy::max_size(_data);
1755 template <
typename T,
typename Policy>
1759 if (capacity_new <= capacity())
1770 template <
typename T,
typename Policy>
1771 typename segment_vector<T, Policy>::size_type
1774 if (_segments_used == 0)
1776 return policy::capacity(_segments_used - 1);
1790 template <
typename T,
typename Policy>
1796 size_type new_last = policy::get_segment(size() - 1);
1797 if (_segments_used - 1 == new_last)
1802 for (size_type i = new_last + 1; i < _segments_used; ++i)
1803 _data[i].free_data();
1804 _segments_used = new_last + 1;
1805 storage::resize(_data, _segments_used);
1820 template <
typename T,
typename Policy>
1826 assert(segment_capacity_validation());
1841 template <
typename T,
typename Policy>
1847 for (size_type i = 0; i < _segments_used; ++i)
1848 _data[i].free_data();
1876 template <
typename T,
typename Policy>
1880 return insert(pos, 1, value);
1906 template <
typename T,
typename Policy>
1910 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1915 get(idx) = std::move(value);
1947 template <
typename T,
typename Policy>
1952 size_type idx =
static_cast<size_type
>(pos -
cbegin());
1956 insert_gap(idx, count);
1957 for (size_type i = idx; i < idx + count; ++i)
1958 get(i) = std::move(value);
1997 template <
typename T,
typename Policy>
1998 template <
typename InputIt,
1999 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2005 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2006 size_type gap_size =
static_cast<size_type
>(std::distance(first, last));
2010 insert_gap(idx, gap_size);
2011 for (size_type i = idx; i < idx + gap_size; ++i, ++first)
2044 template <
typename T,
typename Policy>
2047 std::initializer_list<T> ilist)
2049 return insert(pos, ilist.begin(), ilist.end());
2080 template <
typename T,
typename Policy>
2081 template <
class... Args>
2085 size_type idx =
static_cast<size_type
>(pos -
cbegin());
2090 noexcept(T(std::forward<Args>(args)...))>
2091 tmp(std::forward<Args>(args)...);
2093 get(idx) = std::move(tmp.get());
2123 template <
typename T,
typename Policy>
2124 template <
class... Args>
2125 typename segment_vector<T, Policy>::reference
2128 assert(size() < max_size());
2132 if (size() == capacity())
2133 internal_reserve(capacity() + 1);
2135 size_type segment = policy::get_segment(size());
2136 _data[segment].emplace_back(std::forward<Args>(args)...);
2163 template <
typename T,
typename Policy>
2167 return erase(pos, pos + 1);
2194 template <
typename T,
typename Policy>
2198 size_type count =
static_cast<size_type
>(std::distance(first, last));
2199 size_type idx =
static_cast<size_type
>(first -
cbegin());
2206 size_type _size = size();
2208 if (!std::is_trivially_destructible<T>::value ||
2209 idx + count < _size)
2210 snapshot_data(idx, _size);
2221 size_type middle = policy::get_segment(_size - count);
2222 size_type last = policy::get_segment(_size - 1);
2223 size_type middle_size = policy::index_in_segment(_size - count);
2224 for (size_type s = last; s > middle; --s)
2226 _data[middle].resize(middle_size);
2228 _segments_used = middle + 1;
2231 assert(segment_capacity_validation());
2254 template <
typename T,
typename Policy>
2258 emplace_back(value);
2279 template <
typename T,
typename Policy>
2283 emplace_back(std::move(value));
2299 template <
typename T,
typename Policy>
2308 assert(segment_capacity_validation());
2334 template <
typename T,
typename Policy>
2340 size_type _size = size();
2344 if (capacity() < count)
2345 internal_reserve(count);
2346 construct(_size, count - _size);
2349 assert(segment_capacity_validation());
2376 template <
typename T,
typename Policy>
2382 size_type _size = size();
2386 if (capacity() < count)
2387 internal_reserve(count);
2388 construct(_size, count - _size, value);
2391 assert(segment_capacity_validation());
2397 template <
typename T,
typename Policy>
2403 _data.swap(other._data);
2404 std::swap(_segments_used, other._segments_used);
2423 template <
typename T,
typename Policy>
2427 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2429 if (new_capacity > max_size())
2430 throw std::length_error(
"New capacity exceeds max size.");
2432 if (new_capacity == 0)
2435 size_type old_idx = policy::get_segment(capacity());
2436 size_type new_idx = policy::get_segment(new_capacity - 1);
2437 storage::resize(_data, new_idx + 1);
2438 for (size_type i = old_idx; i <= new_idx; ++i) {
2439 size_type segment_capacity = policy::segment_size(i);
2440 _data[i].reserve(segment_capacity);
2442 _segments_used = new_idx + 1;
2444 assert(segment_capacity_validation());
2473 template <
typename T,
typename Policy>
2474 template <
typename... Args>
2479 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2480 assert(capacity() >= size() + count);
2482 for (size_type i = idx; i < idx + count; ++i) {
2483 size_type segment = policy::get_segment(i);
2484 _data[segment].emplace_back(std::forward<Args>(args)...);
2487 assert(segment_capacity_validation());
2520 template <
typename T,
typename Policy>
2521 template <
typename InputIt,
2522 typename std::enable_if<detail::is_input_iterator<InputIt>::value,
2528 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2529 size_type count =
static_cast<size_type
>(std::distance(first, last));
2530 assert(capacity() >= size() + count);
2532 for (size_type i = idx; i < idx + count; ++i, ++first) {
2533 size_type segment = policy::get_segment(i);
2534 _data[segment].emplace_back(*first);
2537 assert(segment_capacity_validation());
2561 template <
typename T,
typename Policy>
2565 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2569 size_type _size = size();
2571 if (capacity() < _size + count)
2572 internal_reserve(_size + count);
2578 snapshot_data(idx, _size);
2580 resize(_size + count);
2581 std::move_backward(
begin,
end, dest);
2583 assert(segment_capacity_validation());
2605 template <
typename T,
typename Policy>
2609 assert(pmemobj_tx_stage() == TX_STAGE_WORK);
2610 assert(size_new <= size());
2615 if (!std::is_trivially_destructible<T>::value)
2616 snapshot_data(size_new, size());
2618 size_type
begin = policy::get_segment(size() - 1);
2619 size_type
end = policy::get_segment(size_new);
2621 _data[
begin].clear();
2623 size_type residue = policy::index_in_segment(size_new);
2626 assert(segment_capacity_validation());
2636 template <
typename T,
typename Policy>
2640 auto pop = pmemobj_pool_by_ptr(
this);
2641 assert(pop !=
nullptr);
2654 template <
typename T,
typename Policy>
2661 size_type segment = policy::get_segment(first);
2662 size_type
end = policy::get_segment(last - 1);
2663 size_type count = policy::segment_top(segment + 1) - first;
2665 while (segment !=
end) {
2666 detail::conditional_add_to_tx(&cget(first), count,
2667 POBJ_XADD_ASSUME_INITIALIZED);
2668 first = policy::segment_top(++segment);
2669 count = policy::segment_size(segment);
2671 detail::conditional_add_to_tx(&cget(first), last - first,
2672 POBJ_XADD_ASSUME_INITIALIZED);
2680 template <
typename T,
typename Policy>
2681 typename segment_vector<T, Policy>::reference
2684 size_type s_idx = policy::get_segment(n);
2685 size_type local_idx = policy::index_in_segment(n);
2687 return _data[s_idx][local_idx];
2695 template <
typename T,
typename Policy>
2696 typename segment_vector<T, Policy>::const_reference
2699 size_type s_idx = policy::get_segment(n);
2700 size_type local_idx = policy::index_in_segment(n);
2702 return _data[s_idx][local_idx];
2710 template <
typename T,
typename Policy>
2711 typename segment_vector<T, Policy>::const_reference
2714 size_type s_idx = policy::get_segment(n);
2715 size_type local_idx = policy::index_in_segment(n);
2717 return _data[s_idx][local_idx];
2727 template <
typename T,
typename Policy>
2731 for (size_type i = 0; i < _segments_used; ++i)
2732 if (_data.const_at(i).capacity() != policy::segment_size(i))
2743 template <
typename T,
typename Policy>
2764 template <
typename T,
typename Policy>
2788 template <
typename T,
typename Policy>
2793 return !(lhs == rhs);
2808 template <
typename T,
typename Policy>
2813 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.
begin(),
2829 template <
typename T,
typename Policy>
2834 return !(rhs < lhs);
2849 template <
typename T,
typename Policy>
2869 template <
typename T,
typename Policy>
2874 return !(lhs < rhs);
2890 template <
typename T,
typename Policy>
2894 return lhs.
size() == rhs.size() &&
2895 std::equal(lhs.
begin(), lhs.
end(), rhs.begin());
2911 template <
typename T,
typename Policy>
2915 return !(lhs == rhs);
2929 template <
typename T,
typename Policy>
2933 return std::lexicographical_compare(lhs.
begin(), lhs.
end(), rhs.begin(),
2948 template <
typename T,
typename Policy>
2952 return !(std::lexicographical_compare(rhs.begin(), rhs.end(),
2968 template <
typename T,
typename Policy>
2972 return !(lhs <= rhs);
2986 template <
typename T,
typename Policy>
2990 return !(lhs < rhs);
3006 template <
typename T,
typename Policy>
3026 template <
typename T,
typename Policy>
3030 return !(lhs == rhs);
3044 template <
typename T,
typename Policy>
3062 template <
typename T,
typename Policy>
3066 return !(rhs < lhs);
3081 template <
typename T,
typename Policy>
3099 template <
typename T,
typename Policy>
3103 return !(lhs < rhs);