mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
utils/stall_free: introduce reserve_gently
Add reserve_gently() that can reserve memory without stalling by repeatedly calling reserve_partial() method of the passed container. Update the comments of existing reserve_partial() methods to mention this newly introduced reserve_gently() wrapper. Also, add test to verify the functionality. Signed-off-by: Lakshmi Narayanan Sreethar <lakshmi.sreethar@scylladb.com>
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include <random>
|
||||
|
||||
#include "test/lib/scylla_test_case.hh"
|
||||
#include "utils/stall_free.hh"
|
||||
#include "utils/small_vector.hh"
|
||||
@@ -530,3 +532,15 @@ SEASTAR_THREAD_TEST_CASE(test_clear_gently_vector_of_optimized_optionals) {
|
||||
utils::clear_gently(v).get();
|
||||
BOOST_REQUIRE_EQUAL(cleared_gently, 1);
|
||||
}
|
||||
|
||||
SEASTAR_THREAD_TEST_CASE(test_reserve_gently_with_chunked_vector) {
|
||||
auto rand = std::default_random_engine();
|
||||
auto size_dist = std::uniform_int_distribution<unsigned>(1, 1 << 12);
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
utils::chunked_vector<uint8_t, 512> v;
|
||||
const auto size = size_dist(rand);
|
||||
utils::reserve_gently(v, size).get();
|
||||
BOOST_REQUIRE_EQUAL(v.capacity(), size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +191,10 @@ public:
|
||||
///
|
||||
/// Here, `do_until()` takes care of yielding between iterations when
|
||||
/// necessary.
|
||||
///
|
||||
/// The recommended way to use this method is by calling utils::reserve_gently() from stall_free.hh
|
||||
/// instead of looping with this method directly. utils::reserve_gently() will repeatedly call this
|
||||
/// method to reserve the required quantity, yielding between calls when necessary.
|
||||
void reserve_partial(size_t n) {
|
||||
if (n > _capacity) {
|
||||
make_room(n, true);
|
||||
|
||||
@@ -155,6 +155,10 @@ public:
|
||||
///
|
||||
/// Here, `do_until()` takes care of yielding between iterations when
|
||||
/// necessary.
|
||||
///
|
||||
/// The recommended way to use this method is by calling utils::reserve_gently() from stall_free.hh
|
||||
/// instead of looping with this method directly. utils::reserve_gently() will repeatedly call this
|
||||
/// method to reserve the required quantity, yielding between calls when necessary.
|
||||
void reserve_partial(size_t n) {
|
||||
if (n > _capacity) {
|
||||
return make_room(n, true);
|
||||
|
||||
@@ -271,5 +271,24 @@ future<> clear_gently(seastar::optimized_optional<T>& opt) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
concept gently_reservable = requires(T x) {
|
||||
{ x.capacity() } -> std::same_as<size_t>;
|
||||
{ x.reserve_partial(10) } -> std::same_as<void>;
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// reserve_gently gently reserves memory in containers which support partial reserve.
|
||||
future<> reserve_gently(internal::gently_reservable auto& container, size_t size) {
|
||||
return seastar::do_until([&container, size] { return container.capacity() == size; }, [&container, size]() {
|
||||
container.reserve_partial(size);
|
||||
return seastar::make_ready_future();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user