mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-29 11:10:40 +00:00
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:
@@ -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);
|
||||
}
|
||||
@@ -321,6 +321,11 @@ public:
|
||||
bool operator==(const chunked_vector& x) const {
|
||||
return std::ranges::equal(*this, x);
|
||||
}
|
||||
public:
|
||||
iterator insert(const_iterator pos, const T& x);
|
||||
iterator insert(const_iterator pos, T&& x);
|
||||
template <typename... Args>
|
||||
iterator emplace(const_iterator pos, Args&&... args);
|
||||
};
|
||||
|
||||
template<typename T, size_t max_contiguous_allocation>
|
||||
@@ -595,6 +600,34 @@ chunked_vector<T, max_contiguous_allocation>::clear() {
|
||||
shrink_to_fit();
|
||||
}
|
||||
|
||||
template <typename T, size_t max_contiguous_allocation>
|
||||
typename chunked_vector<T, max_contiguous_allocation>::iterator
|
||||
chunked_vector<T, max_contiguous_allocation>::insert(const_iterator pos, const T& x) {
|
||||
auto insert_idx = pos - begin();
|
||||
push_back(x);
|
||||
std::rotate(begin() + insert_idx, end() - 1, end());
|
||||
return begin() + insert_idx;
|
||||
}
|
||||
|
||||
template <typename T, size_t max_contiguous_allocation>
|
||||
typename chunked_vector<T, max_contiguous_allocation>::iterator
|
||||
chunked_vector<T, max_contiguous_allocation>::insert(const_iterator pos, T&& x) {
|
||||
auto insert_idx = pos - begin();
|
||||
push_back(std::move(x));
|
||||
std::rotate(begin() + insert_idx, end() - 1, end());
|
||||
return begin() + insert_idx;
|
||||
}
|
||||
|
||||
template <typename T, size_t max_contiguous_allocation>
|
||||
template <typename... Args>
|
||||
typename chunked_vector<T, max_contiguous_allocation>::iterator
|
||||
chunked_vector<T, max_contiguous_allocation>::emplace(const_iterator pos, Args&&... args) {
|
||||
auto insert_idx = pos - begin();
|
||||
emplace_back(std::forward<Args>(args)...);
|
||||
std::rotate(begin() + insert_idx, end() - 1, end());
|
||||
return begin() + insert_idx;
|
||||
}
|
||||
|
||||
template <typename T, size_t max_contiguous_allocation>
|
||||
std::ostream& operator<<(std::ostream& os, const chunked_vector<T, max_contiguous_allocation>& v) {
|
||||
fmt::print(os, "{}", v);
|
||||
|
||||
Reference in New Issue
Block a user