From 81891a6c314ae50151f379b145288d465a420c6c Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 May 2025 14:20:12 +0300 Subject: [PATCH 1/4] utils: chunked_vector: add range insert() overloads Inserts an iterator range at some position. Again we insert the range at the end and use std::rotate() to move the newly inserted elements into place, forgoing possible optimizations. Unit tests are added. (cherry picked from commit 24e0d17defda59ea31a66beadb666049a79f4ffd) --- test/boost/chunked_vector_test.cc | 22 +++++++++++++++++++++- utils/chunked_vector.hh | 14 ++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/test/boost/chunked_vector_test.cc b/test/boost/chunked_vector_test.cc index 8ed9ec085c..764eef691d 100644 --- a/test/boost/chunked_vector_test.cc +++ b/test/boost/chunked_vector_test.cc @@ -32,7 +32,7 @@ using deque = std::deque; BOOST_AUTO_TEST_CASE(test_random_walk) { auto rand = std::default_random_engine(); - auto op_gen = std::uniform_int_distribution(0, 12); + auto op_gen = std::uniform_int_distribution(0, 13); auto nr_dist = std::geometric_distribution(0.7); deque d; disk_array c; @@ -127,6 +127,15 @@ BOOST_AUTO_TEST_CASE(test_random_walk) { d.erase(d.begin() + start, d.begin() + end); break; } + case 13: { + auto start = std::uniform_int_distribution(0, d.size())(rand); + auto nr = std::uniform_int_distribution(0, 20)(rand); + auto n = rand(); + auto data = std::views::iota(n, n + nr); + c.insert(c.begin() + start, data.begin(), data.end()); + d.insert(d.begin() + start, data.begin(), data.end()); + break; + } default: abort(); } @@ -552,3 +561,14 @@ BOOST_AUTO_TEST_CASE(test_erase_single) { BOOST_REQUIRE_EQUAL(vec[0], 2); BOOST_REQUIRE_EQUAL(vec[1], 8); } + +BOOST_AUTO_TEST_CASE(test_insert_range) { + auto vec = utils::chunked_vector(); + vec.push_back(1); + vec.push_back(2); + vec.push_back(3); + vec.push_back(4); + auto data = std::views::iota(8, 12); + vec.insert(vec.begin() + 2, data.begin(), data.end()); + BOOST_REQUIRE(std::ranges::equal(vec, std::array{1, 2, 8, 9, 10, 11, 3, 4})); +} diff --git a/utils/chunked_vector.hh b/utils/chunked_vector.hh index a5e90f22bf..efbed9e885 100644 --- a/utils/chunked_vector.hh +++ b/utils/chunked_vector.hh @@ -324,6 +324,8 @@ public: public: iterator insert(const_iterator pos, const T& x); iterator insert(const_iterator pos, T&& x); + template + iterator insert(const_iterator post, Iterator first, Iterator last); template iterator emplace(const_iterator pos, Args&&... args); iterator erase(iterator pos); @@ -622,6 +624,18 @@ chunked_vector::insert(const_iterator pos, T&& x) return begin() + insert_idx; } +template +template +typename chunked_vector::iterator +chunked_vector::insert(const_iterator pos, Iterator first, Iterator last) { + auto insert_idx = pos - begin(); + auto n_insert = std::distance(first, last); + reserve(size() + n_insert); + std::copy(first, last, std::back_inserter(*this)); + std::rotate(begin() + insert_idx, end() - n_insert, end()); + return begin() + insert_idx; +} + template template typename chunked_vector::iterator From 951841f71fc4fc463d4f427c5e91038e6bec767a Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 May 2025 14:23:57 +0300 Subject: [PATCH 2/4] utils: chunked_vector: add swap() method Following std::vector(), we implement swap(). It's a simple matter of swapping all the contents. A unit test is added. (cherry picked from commit 13a75ff835f421ba6410ef2c0d113c98bf53db4e) --- test/boost/chunked_vector_test.cc | 12 ++++++++++++ utils/chunked_vector.hh | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/test/boost/chunked_vector_test.cc b/test/boost/chunked_vector_test.cc index 764eef691d..cb78aeb02e 100644 --- a/test/boost/chunked_vector_test.cc +++ b/test/boost/chunked_vector_test.cc @@ -572,3 +572,15 @@ BOOST_AUTO_TEST_CASE(test_insert_range) { vec.insert(vec.begin() + 2, data.begin(), data.end()); BOOST_REQUIRE(std::ranges::equal(vec, std::array{1, 2, 8, 9, 10, 11, 3, 4})); } + +BOOST_AUTO_TEST_CASE(test_swap) { + auto v1 = utils::chunked_vector(); + auto v2 = utils::chunked_vector(); + + v1.push_back(1); + v2.push_back(2); + v2.push_back(4); + v1.swap(v2); + BOOST_REQUIRE(std::ranges::equal(v1, std::array{2, 4})); + BOOST_REQUIRE(std::ranges::equal(v2, std::array{1})); +} diff --git a/utils/chunked_vector.hh b/utils/chunked_vector.hh index efbed9e885..bd3d7d7b99 100644 --- a/utils/chunked_vector.hh +++ b/utils/chunked_vector.hh @@ -332,6 +332,7 @@ public: iterator erase(const_iterator pos); iterator erase(iterator first, iterator last); iterator erase(const_iterator first, const_iterator last); + void swap(chunked_vector& x) noexcept; }; template @@ -674,6 +675,15 @@ chunked_vector::erase(iterator pos) { return erase(const_iterator(pos)); } +template +void +chunked_vector::swap(chunked_vector& x) noexcept { + using std::swap; + swap(_chunks, x._chunks); + swap(_size, x._size); + swap(_capacity, x._capacity); +} + template std::ostream& operator<<(std::ostream& os, const chunked_vector& v) { fmt::print(os, "{}", v); From 1c2a4540ebf02ee329380e92f2438513cb7ceb49 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Wed, 14 May 2025 19:54:06 +0300 Subject: [PATCH 3/4] partition_range_compat: generalize wrap/unwrap helpers These helpers convert vectors of wrapped intervals to vectors of unwrapped intervals and vice versa. Generalize them to work on any sequence type. This is in preparation of moving from vectors to chunked_vectors. (cherry picked from commit 83c2a2e169785dbed9eba689f3b321cb76ed2c39) Backport notes: due to compiler limitations in this toolchain, the template template parameter was replaced by elaborate metaprogramming to detect the value type and rebind the container to a new value type. --- partition_range_compat.hh | 119 ++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/partition_range_compat.hh b/partition_range_compat.hh index a2351b1c3e..8f57793ae4 100644 --- a/partition_range_compat.hh +++ b/partition_range_compat.hh @@ -20,10 +20,16 @@ using wrapping_partition_range = wrapping_interval; // unwraps a vector of wrapping ranges into a vector of nonwrapping ranges // if the vector happens to be sorted by the left bound, it remains sorted -template -std::vector> -unwrap(std::vector>&& v, Comparator&& cmp) { - std::vector> ret; +template