utils: chunked_vector: implement insert() for single-element inserts

partition_range_compat's unwrap() needs insert if we are to
use it for chunked_vector (which we do).

Implement using push_back() and std::rotate().

emplace(iterator, args) is also implemented, though the benefit
is diluted (it will be moved after construction).

The implementation isn't optimal - if T is trivially copyable
then using std::memmove() will be much faster that std::rotate(),
but this complex optimization is left for later.

Unit tests are added.

(cherry picked from commit 5301f3d0b5)
This commit is contained in:
Avi Kivity
2025-05-13 22:57:29 +03:00
committed by Asias He
parent 23bcff5c52
commit efad391fac
2 changed files with 75 additions and 1 deletions

View File

@@ -32,7 +32,7 @@ using deque = std::deque<int>;
BOOST_AUTO_TEST_CASE(test_random_walk) {
auto rand = std::default_random_engine();
auto op_gen = std::uniform_int_distribution<unsigned>(0, 9);
auto op_gen = std::uniform_int_distribution<unsigned>(0, 10);
auto nr_dist = std::geometric_distribution<size_t>(0.7);
deque d;
disk_array c;
@@ -105,6 +105,13 @@ BOOST_AUTO_TEST_CASE(test_random_walk) {
d.resize(nr);
break;
}
case 10: {
auto pos = std::uniform_int_distribution<size_t>(0, d.size())(rand);
auto n = rand();
c.insert(c.begin() + pos, n);
d.insert(d.begin() + pos, n);
break;
}
default:
abort();
}
@@ -467,3 +474,37 @@ BOOST_AUTO_TEST_CASE(test_value_init_ctor) {
BOOST_REQUIRE_EQUAL(*it, v);
}
}
BOOST_AUTO_TEST_CASE(test_insert_single) {
auto vec = utils::chunked_vector<int, 8>();
auto r1 = vec.insert(vec.begin(), 1);
BOOST_REQUIRE_EQUAL(vec.size(), 1);
BOOST_REQUIRE_EQUAL(r1 - std::begin(vec), 0);
BOOST_REQUIRE_EQUAL(vec[0], 1);
auto r2 = vec.insert(vec.begin(), 2);
BOOST_REQUIRE_EQUAL(vec.size(), 2);
BOOST_REQUIRE_EQUAL(r2 - std::begin(vec), 0);
BOOST_REQUIRE_EQUAL(vec[0], 2);
BOOST_REQUIRE_EQUAL(vec[1], 1);
auto r3 = vec.insert(vec.end(), 3);
BOOST_REQUIRE_EQUAL(vec.size(), 3);
BOOST_REQUIRE_EQUAL(r3 - std::begin(vec), 2);
BOOST_REQUIRE_EQUAL(vec[0], 2);
BOOST_REQUIRE_EQUAL(vec[1], 1);
BOOST_REQUIRE_EQUAL(vec[2], 3);
auto r4 = vec.insert(vec.end() - 2, 4);
BOOST_REQUIRE_EQUAL(vec.size(), 4);
BOOST_REQUIRE_EQUAL(r4 - std::begin(vec), 1);
BOOST_REQUIRE_EQUAL(vec[0], 2);
BOOST_REQUIRE_EQUAL(vec[1], 4);
BOOST_REQUIRE_EQUAL(vec[2], 1);
BOOST_REQUIRE_EQUAL(vec[3], 3);
auto r5 = vec.emplace(vec.end() - 2, 6);
BOOST_REQUIRE_EQUAL(vec.size(), 5);
BOOST_REQUIRE_EQUAL(r5 - std::begin(vec), 2);
BOOST_REQUIRE_EQUAL(vec[0], 2);
BOOST_REQUIRE_EQUAL(vec[1], 4);
BOOST_REQUIRE_EQUAL(vec[2], 6);
BOOST_REQUIRE_EQUAL(vec[3], 1);
BOOST_REQUIRE_EQUAL(vec[4], 3);
}