summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/CMakeLists.txt1
-rw-r--r--vespalib/src/tests/datastore/fixed_size_hash_map/fixed_size_hash_map_test.cpp4
-rw-r--r--vespalib/src/tests/util/generation_hold_list/generation_hold_list_test.cpp3
-rw-r--r--vespalib/src/tests/util/generation_holder/CMakeLists.txt9
-rw-r--r--vespalib/src/tests/util/generation_holder/generation_holder_test.cpp38
-rw-r--r--vespalib/src/tests/util/rcuvector/rcuvector_test.cpp44
-rw-r--r--vespalib/src/vespa/vespalib/datastore/datastorebase.cpp14
-rw-r--r--vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp12
-rw-r--r--vespalib/src/vespa/vespalib/util/generation_hold_list.h7
-rw-r--r--vespalib/src/vespa/vespalib/util/generation_hold_list.hpp31
-rw-r--r--vespalib/src/vespa/vespalib/util/generationholder.cpp55
-rw-r--r--vespalib/src/vespa/vespalib/util/generationholder.h64
-rw-r--r--vespalib/src/vespa/vespalib/util/rcuvector.hpp12
13 files changed, 81 insertions, 213 deletions
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt
index 532ec870ce9..8edd7fb2c5d 100644
--- a/vespalib/CMakeLists.txt
+++ b/vespalib/CMakeLists.txt
@@ -182,7 +182,6 @@ vespa_define_module(
src/tests/util/cgroup_resource_limits
src/tests/util/file_area_freelist
src/tests/util/generation_hold_list
- src/tests/util/generation_holder
src/tests/util/generationhandler
src/tests/util/generationhandler_stress
src/tests/util/hamming
diff --git a/vespalib/src/tests/datastore/fixed_size_hash_map/fixed_size_hash_map_test.cpp b/vespalib/src/tests/datastore/fixed_size_hash_map/fixed_size_hash_map_test.cpp
index 599cb209e6c..ad10bc5c7e6 100644
--- a/vespalib/src/tests/datastore/fixed_size_hash_map/fixed_size_hash_map_test.cpp
+++ b/vespalib/src/tests/datastore/fixed_size_hash_map/fixed_size_hash_map_test.cpp
@@ -90,11 +90,11 @@ DataStoreFixedSizeHashTest::commit()
{
_store.transferHoldLists(_generation_handler.getCurrentGeneration());
_hash_map->transfer_hold_lists(_generation_handler.getCurrentGeneration());
- _generation_holder.transferHoldLists(_generation_handler.getCurrentGeneration());
+ _generation_holder.assign_generation(_generation_handler.getCurrentGeneration());
_generation_handler.incGeneration();
_store.trimHoldLists(_generation_handler.getFirstUsedGeneration());
_hash_map->trim_hold_lists(_generation_handler.getFirstUsedGeneration());
- _generation_holder.trimHoldLists(_generation_handler.getFirstUsedGeneration());
+ _generation_holder.reclaim(_generation_handler.getFirstUsedGeneration());
}
size_t
diff --git a/vespalib/src/tests/util/generation_hold_list/generation_hold_list_test.cpp b/vespalib/src/tests/util/generation_hold_list/generation_hold_list_test.cpp
index 0490a99f1e0..8305b711d5f 100644
--- a/vespalib/src/tests/util/generation_hold_list/generation_hold_list_test.cpp
+++ b/vespalib/src/tests/util/generation_hold_list/generation_hold_list_test.cpp
@@ -3,12 +3,13 @@
#include <vespa/vespalib/gtest/gtest.h>
#include <vespa/vespalib/util/generation_hold_list.hpp>
#include <vespa/vespalib/util/generationholder.h>
+#include <iostream>
using vespalib::GenerationHeldBase;
using vespalib::GenerationHoldList;
using MyElem = GenerationHeldBase;
-using MyHoldList = GenerationHoldList<MyElem::UP, true>;
+using MyHoldList = GenerationHoldList<MyElem::UP, true, false>;
TEST(GenerationHoldListTest, holding_of_unique_ptr_elements_with_tracking_of_held_bytes)
{
diff --git a/vespalib/src/tests/util/generation_holder/CMakeLists.txt b/vespalib/src/tests/util/generation_holder/CMakeLists.txt
deleted file mode 100644
index 8acf9fadaff..00000000000
--- a/vespalib/src/tests/util/generation_holder/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(vespalib_generation_holder_test_app TEST
- SOURCES
- generation_holder_test.cpp
- DEPENDS
- vespalib
- GTest::GTest
-)
-vespa_add_test(NAME vespalib_generation_holder_test_app COMMAND vespalib_generation_holder_test_app)
diff --git a/vespalib/src/tests/util/generation_holder/generation_holder_test.cpp b/vespalib/src/tests/util/generation_holder/generation_holder_test.cpp
deleted file mode 100644
index 97c3330ac9e..00000000000
--- a/vespalib/src/tests/util/generation_holder/generation_holder_test.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include <vespa/vespalib/gtest/gtest.h>
-#include <vespa/vespalib/util/generationholder.h>
-
-using vespalib::GenerationHolder;
-using MyHeld = vespalib::GenerationHeldBase;
-
-TEST(GenerationHolderTest, basic_tracking)
-{
- GenerationHolder gh;
- gh.hold(std::make_unique<MyHeld>(sizeof(int32_t)));
- gh.transferHoldLists(0);
- gh.hold(std::make_unique<MyHeld>(sizeof(int32_t)));
- gh.transferHoldLists(1);
- gh.hold(std::make_unique<MyHeld>(sizeof(int32_t)));
- gh.transferHoldLists(2);
- gh.hold(std::make_unique<MyHeld>(sizeof(int32_t)));
- gh.transferHoldLists(4);
- EXPECT_EQ(4u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(0);
- EXPECT_EQ(4u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(1);
- EXPECT_EQ(3u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(2);
- EXPECT_EQ(2u * sizeof(int32_t), gh.getHeldBytes());
- gh.hold(std::make_unique<MyHeld>(sizeof(int32_t)));
- gh.transferHoldLists(6);
- EXPECT_EQ(3u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(6);
- EXPECT_EQ(1u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(7);
- EXPECT_EQ(0u * sizeof(int32_t), gh.getHeldBytes());
- gh.trimHoldLists(7);
- EXPECT_EQ(0u * sizeof(int32_t), gh.getHeldBytes());
-}
-
-GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/vespalib/src/tests/util/rcuvector/rcuvector_test.cpp b/vespalib/src/tests/util/rcuvector/rcuvector_test.cpp
index eb2b00f9e20..c23065b7468 100644
--- a/vespalib/src/tests/util/rcuvector/rcuvector_test.cpp
+++ b/vespalib/src/tests/util/rcuvector/rcuvector_test.cpp
@@ -102,15 +102,15 @@ TEST(RcuVectorTest, resize)
RcuVectorBase<int8_t> v(growStrategy(16, 1.0, 0), g);
v.push_back(1);
v.push_back(2);
- g.transferHoldLists(0);
- g.trimHoldLists(1);
+ g.assign_generation(0);
+ g.reclaim(1);
const int8_t *old = &v[0];
EXPECT_EQ(16u, v.capacity());
EXPECT_EQ(2u, v.size());
v.ensure_size(32, 3);
v[0] = 3;
v[1] = 3;
- g.transferHoldLists(1);
+ g.assign_generation(1);
EXPECT_EQ(1, old[0]);
EXPECT_EQ(2, old[1]);
EXPECT_EQ(3, v[0]);
@@ -119,7 +119,7 @@ TEST(RcuVectorTest, resize)
EXPECT_EQ(3, v[31]);
EXPECT_EQ(64u, v.capacity());
EXPECT_EQ(32u, v.size());
- g.trimHoldLists(2);
+ g.reclaim(2);
}
}
@@ -197,11 +197,11 @@ void verify_shrink_with_buffer_copying(size_t initial_size, size_t absolute_mini
v.push_back(2);
v.push_back(3);
v.push_back(4);
- g.transferHoldLists(0);
- g.trimHoldLists(1);
+ g.assign_generation(0);
+ g.reclaim(1);
MemoryUsage mu;
mu = v.getMemoryUsage();
- mu.incAllocatedBytesOnHold(g.getHeldBytes());
+ mu.incAllocatedBytesOnHold(g.get_held_bytes());
EXPECT_TRUE(assertUsage(MemoryUsage(initial_capacity, 4, 0, 0), mu));
EXPECT_EQ(4u, v.size());
EXPECT_EQ(initial_capacity, v.capacity());
@@ -211,18 +211,18 @@ void verify_shrink_with_buffer_copying(size_t initial_size, size_t absolute_mini
EXPECT_EQ(4, v[3]);
const int8_t *old = &v[0];
v.shrink(2);
- g.transferHoldLists(1);
+ g.assign_generation(1);
EXPECT_EQ(2u, v.size());
EXPECT_EQ(minimal_capacity, v.capacity());
EXPECT_EQ(1, v[0]);
EXPECT_EQ(2, v[1]);
EXPECT_EQ(1, old[0]);
EXPECT_EQ(2, old[1]);
- g.trimHoldLists(2);
+ g.reclaim(2);
EXPECT_EQ(1, v[0]);
EXPECT_EQ(2, v[1]);
mu = v.getMemoryUsage();
- mu.incAllocatedBytesOnHold(g.getHeldBytes());
+ mu.incAllocatedBytesOnHold(g.get_held_bytes());
EXPECT_TRUE(assertUsage(MemoryUsage(minimal_capacity, 2, 0, 0), mu));
}
@@ -256,7 +256,7 @@ struct ShrinkFixture {
EXPECT_EQ(oldPtr, &vec[0]);
}
void assertEmptyHoldList() {
- EXPECT_EQ(0u, g.getHeldBytes());
+ EXPECT_EQ(0u, g.get_held_bytes());
}
static size_t page_ints() { return round_up_to_page_size(1) / sizeof(int); }
};
@@ -294,8 +294,8 @@ TEST(RcuVectorTest, small_expand)
v.push_back(2);
EXPECT_EQ(2u, v.capacity());
EXPECT_EQ(2u, v.size());
- g.transferHoldLists(1);
- g.trimHoldLists(2);
+ g.assign_generation(1);
+ g.reclaim(2);
}
struct FixtureBase {
@@ -325,10 +325,10 @@ struct Fixture : public FixtureBase {
Fixture();
~Fixture();
- void transfer_and_trim(generation_t transfer_gen, generation_t trim_gen)
+ void assign_and_reclaim(generation_t assign_gen, generation_t reclaim_gen)
{
- g.transferHoldLists(transfer_gen);
- g.trimHoldLists(trim_gen);
+ g.assign_generation(assign_gen);
+ g.reclaim(reclaim_gen);
}
};
@@ -345,7 +345,7 @@ TEST(RcuVectorTest, memory_allocator_can_be_set)
{
Fixture f;
EXPECT_EQ(AllocStats(2, 0), f.stats);
- f.transfer_and_trim(1, 2);
+ f.assign_and_reclaim(1, 2);
EXPECT_EQ(AllocStats(2, 1), f.stats);
}
@@ -355,7 +355,7 @@ TEST(RcuVectorTest, memory_allocator_is_preserved_across_reset)
f.arr.reset();
f.arr.reserve(100);
EXPECT_EQ(AllocStats(4, 1), f.stats);
- f.transfer_and_trim(1, 2);
+ f.assign_and_reclaim(1, 2);
EXPECT_EQ(AllocStats(4, 3), f.stats);
}
@@ -366,7 +366,7 @@ TEST(RcuVectorTest, created_replacement_vector_uses_same_memory_allocator)
EXPECT_EQ(AllocStats(2, 0), f.stats);
arr2.reserve(100);
EXPECT_EQ(AllocStats(3, 0), f.stats);
- f.transfer_and_trim(1, 2);
+ f.assign_and_reclaim(1, 2);
EXPECT_EQ(AllocStats(3, 1), f.stats);
}
@@ -377,7 +377,7 @@ TEST(RcuVectorTest, ensure_size_and_shrink_use_same_memory_allocator)
EXPECT_EQ(AllocStats(3, 0), f.stats);
f.arr.shrink(1000);
EXPECT_EQ(AllocStats(4, 0), f.stats);
- f.transfer_and_trim(1, 2);
+ f.assign_and_reclaim(1, 2);
EXPECT_EQ(AllocStats(4, 3), f.stats);
}
@@ -432,10 +432,10 @@ void
StressFixture::commit()
{
auto current_gen = generation_handler.getCurrentGeneration();
- g.transferHoldLists(current_gen);
+ g.assign_generation(current_gen);
generation_handler.incGeneration();
auto first_used_gen = generation_handler.getFirstUsedGeneration();
- g.trimHoldLists(first_used_gen);
+ g.reclaim(first_used_gen);
}
void
diff --git a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
index dd6c767e9c6..5962e6cf2f7 100644
--- a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp
@@ -232,7 +232,7 @@ DataStoreBase::transferElemHoldList(generation_t generation)
void
DataStoreBase::transferHoldLists(generation_t generation)
{
- _genHolder.transferHoldLists(generation);
+ _genHolder.assign_generation(generation);
if (hasElemHold1()) {
transferElemHoldList(generation);
}
@@ -250,7 +250,7 @@ void
DataStoreBase::trimHoldLists(generation_t usedGen)
{
trimElemHoldList(usedGen); // Trim entries before trimming buffers
- _genHolder.trimHoldLists(usedGen);
+ _genHolder.reclaim(usedGen);
}
void
@@ -258,7 +258,7 @@ DataStoreBase::clearHoldLists()
{
transferElemHoldList(0);
clearElemHoldList();
- _genHolder.clearHoldLists();
+ _genHolder.reclaim_all();
}
void
@@ -268,7 +268,7 @@ DataStoreBase::dropBuffers()
for (uint32_t bufferId = 0; bufferId < numBuffers; ++bufferId) {
_states[bufferId].dropBuffer(bufferId, _buffers[bufferId].get_atomic_buffer());
}
- _genHolder.clearHoldLists();
+ _genHolder.reclaim_all();
}
vespalib::MemoryUsage
@@ -289,7 +289,7 @@ DataStoreBase::holdBuffer(uint32_t bufferId)
_states[bufferId].onHold(bufferId);
size_t holdBytes = 0u; // getMemStats() still accounts held buffers
auto hold = std::make_unique<BufferHold>(holdBytes, *this, bufferId);
- _genHolder.hold(std::move(hold));
+ _genHolder.insert(std::move(hold));
}
void
@@ -356,7 +356,7 @@ DataStoreBase::getMemStats() const
LOG_ABORT("should not be reached");
}
}
- size_t genHolderHeldBytes = _genHolder.getHeldBytes();
+ size_t genHolderHeldBytes = _genHolder.get_held_bytes();
stats._holdBytes += genHolderHeldBytes;
stats._allocBytes += genHolderHeldBytes;
stats._usedBytes += genHolderHeldBytes;
@@ -428,7 +428,7 @@ DataStoreBase::fallbackResize(uint32_t bufferId, size_t elemsNeeded)
state.getTypeHandler(),
state.getTypeId());
if (!_initializing) {
- _genHolder.hold(std::move(hold));
+ _genHolder.insert(std::move(hold));
}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp
index 2ae22084472..102aa1cefb3 100644
--- a/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp
+++ b/vespalib/src/vespa/vespalib/datastore/sharded_hash_map.cpp
@@ -32,7 +32,7 @@ ShardedHashMap::ShardedHashMap(std::unique_ptr<const EntryComparator> comp)
ShardedHashMap::~ShardedHashMap()
{
- _gen_holder.clearHoldLists();
+ _gen_holder.reclaim_all();
for (size_t i = 0; i < num_shards; ++i) {
auto map = _maps[i].load(std::memory_order_relaxed);
delete map;
@@ -58,7 +58,7 @@ ShardedHashMap::hold_shard(std::unique_ptr<const FixedSizeHashMap> map)
{
auto usage = map->get_memory_usage();
auto hold = std::make_unique<ShardedHashMapShardHeld>(usage.allocatedBytes(), std::move(map));
- _gen_holder.hold(std::move(hold));
+ _gen_holder.insert(std::move(hold));
}
ShardedHashMap::KvType&
@@ -115,7 +115,7 @@ ShardedHashMap::transfer_hold_lists(generation_t generation)
map->transfer_hold_lists(generation);
}
}
- _gen_holder.transferHoldLists(generation);
+ _gen_holder.assign_generation(generation);
}
void
@@ -127,7 +127,7 @@ ShardedHashMap::trim_hold_lists(generation_t first_used)
map->trim_hold_lists(first_used);
}
}
- _gen_holder.trimHoldLists(first_used);
+ _gen_holder.reclaim(first_used);
}
size_t
@@ -153,7 +153,7 @@ ShardedHashMap::get_memory_usage() const
memory_usage.merge(map->get_memory_usage());
}
}
- size_t gen_holder_held_bytes = _gen_holder.getHeldBytes();
+ size_t gen_holder_held_bytes = _gen_holder.get_held_bytes();
memory_usage.incAllocatedBytes(gen_holder_held_bytes);
memory_usage.incAllocatedBytesOnHold(gen_holder_held_bytes);
return memory_usage;
@@ -222,7 +222,7 @@ ShardedHashMap::foreach_value(std::function<void(const std::vector<EntryRef>&)>
bool
ShardedHashMap::has_held_buffers() const
{
- return _gen_holder.getHeldBytes() != 0;
+ return _gen_holder.get_held_bytes() != 0;
}
void
diff --git a/vespalib/src/vespa/vespalib/util/generation_hold_list.h b/vespalib/src/vespa/vespalib/util/generation_hold_list.h
index 5e12cb72bbd..b2f90934e84 100644
--- a/vespalib/src/vespa/vespalib/util/generation_hold_list.h
+++ b/vespalib/src/vespa/vespalib/util/generation_hold_list.h
@@ -14,7 +14,7 @@ namespace vespalib {
*
* This class must be used in accordance with a GenerationHandler.
*/
-template <typename T, bool track_bytes_held>
+template <typename T, bool track_bytes_held, bool use_deque>
class GenerationHoldList {
private:
using generation_t = vespalib::GenerationHandler::generation_t;
@@ -30,7 +30,9 @@ private:
};
using ElemList = std::vector<T>;
- using ElemWithGenList = std::deque<ElemWithGen>;
+ using ElemWithGenList = std::conditional_t<use_deque,
+ std::deque<ElemWithGen>,
+ std::vector<ElemWithGen>>;
ElemList _phase_1_list;
ElemWithGenList _phase_2_list;
@@ -46,6 +48,7 @@ private:
public:
GenerationHoldList();
+ ~GenerationHoldList();
/**
* Insert the given data element on this hold list.
diff --git a/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp b/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp
index e7eee2b0aef..ed4a99c4753 100644
--- a/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp
+++ b/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp
@@ -1,12 +1,15 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#pragma once
+
#include "generation_hold_list.h"
+#include <cassert>
namespace vespalib {
-template <typename T, bool track_bytes_held>
+template <typename T, bool track_bytes_held, bool use_deque>
void
-GenerationHoldList<T, track_bytes_held>::assign_generation_internal(generation_t current_gen)
+GenerationHoldList<T, track_bytes_held, use_deque>::assign_generation_internal(generation_t current_gen)
{
for (auto& elem : _phase_1_list) {
_phase_2_list.push_back(ElemWithGen(std::move(elem), current_gen));
@@ -14,9 +17,9 @@ GenerationHoldList<T, track_bytes_held>::assign_generation_internal(generation_t
_phase_1_list.clear();
}
-template <typename T, bool track_bytes_held>
+template <typename T, bool track_bytes_held, bool use_deque>
void
-GenerationHoldList<T, track_bytes_held>::reclaim_internal(generation_t oldest_used_gen)
+GenerationHoldList<T, track_bytes_held, use_deque>::reclaim_internal(generation_t oldest_used_gen)
{
auto itr = _phase_2_list.begin();
auto ite = _phase_2_list.end();
@@ -33,17 +36,25 @@ GenerationHoldList<T, track_bytes_held>::reclaim_internal(generation_t oldest_us
}
}
-template <typename T, bool track_bytes_held>
-GenerationHoldList<T, track_bytes_held>::GenerationHoldList()
+template <typename T, bool track_bytes_held, bool use_deque>
+GenerationHoldList<T, track_bytes_held, use_deque>::GenerationHoldList()
: _phase_1_list(),
_phase_2_list(),
_held_bytes()
{
}
-template <typename T, bool track_bytes_held>
+template <typename T, bool track_bytes_held, bool use_deque>
+GenerationHoldList<T, track_bytes_held, use_deque>::~GenerationHoldList()
+{
+ assert(_phase_1_list.empty());
+ assert(_phase_2_list.empty());
+ assert(get_held_bytes() == 0);
+}
+
+template <typename T, bool track_bytes_held, bool use_deque>
void
-GenerationHoldList<T, track_bytes_held>::insert(T data)
+GenerationHoldList<T, track_bytes_held, use_deque>::insert(T data)
{
_phase_1_list.push_back(std::move(data));
if (track_bytes_held) {
@@ -51,9 +62,9 @@ GenerationHoldList<T, track_bytes_held>::insert(T data)
}
}
-template <typename T, bool track_bytes_held>
+template <typename T, bool track_bytes_held, bool use_deque>
void
-GenerationHoldList<T, track_bytes_held>::reclaim_all()
+GenerationHoldList<T, track_bytes_held, use_deque>::reclaim_all()
{
_phase_1_list.clear();
_phase_2_list.clear();
diff --git a/vespalib/src/vespa/vespalib/util/generationholder.cpp b/vespalib/src/vespa/vespalib/util/generationholder.cpp
index f2b10ff3af1..5f31f610c68 100644
--- a/vespalib/src/vespa/vespalib/util/generationholder.cpp
+++ b/vespalib/src/vespa/vespalib/util/generationholder.cpp
@@ -1,66 +1,15 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "generationholder.h"
-#include <cassert>
+#include "generation_hold_list.hpp"
namespace vespalib {
GenerationHeldBase::~GenerationHeldBase() = default;
GenerationHolder::GenerationHolder()
- : _hold1List(),
- _hold2List(),
- _heldBytes(0)
-{ }
-
-GenerationHolder::~GenerationHolder()
-{
- assert(_hold1List.empty());
- assert(_hold2List.empty());
- assert(getHeldBytes() == 0);
-}
-
-void
-GenerationHolder::hold(GenerationHeldBase::UP data)
-{
- _hold1List.push_back(std::move(data));
- _heldBytes.store(getHeldBytes() + _hold1List.back()->byte_size(), std::memory_order_relaxed);
-}
-
-void
-GenerationHolder::transferHoldListsSlow(generation_t generation)
-{
- HoldList::iterator it(_hold1List.begin());
- HoldList::iterator ite(_hold1List.end());
- HoldList &hold2List = _hold2List;
- for (; it != ite; ++it) {
- assert((*it)->_generation == 0u);
- (*it)->_generation = generation;
- hold2List.push_back(std::move(*it));
- }
- _hold1List.clear();
-}
-
-void
-GenerationHolder::trimHoldListsSlow(generation_t usedGen)
-{
- for (;;) {
- if (_hold2List.empty())
- break;
- GenerationHeldBase &first = *_hold2List.front();
- if (static_cast<sgeneration_t>(first._generation - usedGen) >= 0)
- break;
- _heldBytes.store(getHeldBytes() - first.byte_size(), std::memory_order_relaxed);
- _hold2List.erase(_hold2List.begin());
- }
-}
-
-void
-GenerationHolder::clearHoldLists()
+ : GenerationHoldList<GenerationHeldBase::UP, true, false>()
{
- _hold1List.clear();
- _hold2List.clear();
- _heldBytes = 0;
}
}
diff --git a/vespalib/src/vespa/vespalib/util/generationholder.h b/vespalib/src/vespa/vespalib/util/generationholder.h
index df44f39ebff..ec2cded2e84 100644
--- a/vespalib/src/vespa/vespalib/util/generationholder.h
+++ b/vespalib/src/vespa/vespalib/util/generationholder.h
@@ -2,8 +2,8 @@
#pragma once
+#include "generation_hold_list.h"
#include "generationhandler.h"
-#include <vector>
#include <memory>
namespace vespalib {
@@ -11,79 +11,31 @@ namespace vespalib {
class GenerationHeldBase
{
public:
- typedef GenerationHandler::generation_t generation_t;
- typedef std::unique_ptr<GenerationHeldBase> UP;
- typedef std::shared_ptr<GenerationHeldBase> SP;
+ using generation_t = GenerationHandler::generation_t;
+ using UP = std::unique_ptr<GenerationHeldBase>;
+ using SP = std::shared_ptr<GenerationHeldBase>;
- generation_t _generation;
private:
size_t _byte_size;
public:
GenerationHeldBase(size_t byte_size_in)
- : _generation(0u),
- _byte_size(byte_size_in)
+ : _byte_size(byte_size_in)
{ }
virtual ~GenerationHeldBase();
size_t byte_size() const { return _byte_size; }
};
+template class GenerationHoldList<GenerationHeldBase::UP, true, false>;
+
/*
* GenerationHolder is meant to hold large elements until readers can
* no longer access them.
*/
-class GenerationHolder
-{
-private:
- typedef GenerationHandler::generation_t generation_t;
- typedef GenerationHandler::sgeneration_t sgeneration_t;
-
- typedef std::vector<GenerationHeldBase::UP> HoldList;
-
- HoldList _hold1List;
- HoldList _hold2List;
- std::atomic<size_t> _heldBytes;
-
- /**
- * Transfer holds from hold1 to hold2 lists, assigning generation.
- */
- void transferHoldListsSlow(generation_t generation);
-
- /**
- * Remove all data elements from this holder where generation < usedGen.
- **/
- void trimHoldListsSlow(generation_t usedGen);
-
+class GenerationHolder : public GenerationHoldList<GenerationHeldBase::UP, true, false> {
public:
GenerationHolder();
- ~GenerationHolder();
-
- /**
- * Add the given data pointer to this holder.
- **/
- void hold(GenerationHeldBase::UP data);
-
- /**
- * Transfer holds from hold1 to hold2 lists, assigning generation.
- */
- void transferHoldLists(generation_t generation) {
- if (!_hold1List.empty()) {
- transferHoldListsSlow(generation);
- }
- }
-
- /**
- * Remove all data elements from this holder where generation < usedGen.
- **/
- void trimHoldLists(generation_t usedGen) {
- if (!_hold2List.empty() && static_cast<sgeneration_t>(_hold2List.front()->_generation - usedGen) < 0) {
- trimHoldListsSlow(usedGen);
- }
- }
-
- void clearHoldLists();
- size_t getHeldBytes() const { return _heldBytes.load(std::memory_order_relaxed); }
};
}
diff --git a/vespalib/src/vespa/vespalib/util/rcuvector.hpp b/vespalib/src/vespa/vespalib/util/rcuvector.hpp
index 97a73a73cc9..e551bb17db0 100644
--- a/vespalib/src/vespa/vespalib/util/rcuvector.hpp
+++ b/vespalib/src/vespa/vespalib/util/rcuvector.hpp
@@ -80,7 +80,7 @@ RcuVectorBase<T>::replaceVector(ArrayType replacement) {
replacement.swap(_data); // atomic switch of underlying data
size_t holdSize = replacement.capacity() * sizeof(T);
auto hold = std::make_unique<RcuVectorHeld<ArrayType>>(holdSize, std::move(replacement));
- _genHolder.hold(std::move(hold));
+ _genHolder.insert(std::move(hold));
onReallocation();
}
@@ -116,7 +116,7 @@ RcuVectorBase<T>::shrink(size_t newSize)
tmpData.swap(_data); // atomic switch of underlying data
size_t holdSize = tmpData.capacity() * sizeof(T);
auto hold = std::make_unique<RcuVectorHeld<ArrayType>>(holdSize, std::move(tmpData));
- _genHolder.hold(std::move(hold));
+ _genHolder.insert(std::move(hold));
onReallocation();
}
}
@@ -162,7 +162,7 @@ template <typename T>
void
RcuVector<T>::onReallocation() {
RcuVectorBase<T>::onReallocation();
- _genHolderStore.transferHoldLists(_generation);
+ _genHolderStore.assign_generation(_generation);
}
template <typename T>
@@ -182,14 +182,14 @@ RcuVector<T>::RcuVector(GrowStrategy growStrategy)
template <typename T>
RcuVector<T>::~RcuVector()
{
- _genHolderStore.clearHoldLists();
+ _genHolderStore.reclaim_all();
}
template <typename T>
void
RcuVector<T>::removeOldGenerations(generation_t firstUsed)
{
- _genHolderStore.trimHoldLists(firstUsed);
+ _genHolderStore.reclaim(firstUsed);
}
template <typename T>
@@ -197,7 +197,7 @@ MemoryUsage
RcuVector<T>::getMemoryUsage() const
{
MemoryUsage retval(RcuVectorBase<T>::getMemoryUsage());
- retval.mergeGenerationHeldBytes(_genHolderStore.getHeldBytes());
+ retval.mergeGenerationHeldBytes(_genHolderStore.get_held_bytes());
return retval;
}