8000 Make async registry data structure generic by jvolmer · Pull Request #21699 · arangodb/arangodb · GitHub
[go: up one dir, main page]

Skip to content

Make async registry data structure generic #21699

8000 New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 28, 2025
Prev Previous commit
Next Next commit
Add external gc
  • Loading branch information
jvolmer committed Apr 14, 2025
commit d2643db94435b64b8cc9f9da0702b483e38660dc
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ concept IteratorOverNodes = requires(List l, F f) {
template<typename List, typename Item, typename F>
concept IteratorOverSnapshots =
IteratorOverNodes<List, F> && std::invocable<F, typename Item::Snapshot>;
template<typename T>
concept HasExernalGarbageCollection = requires(T t) {
t.garbage_collect_external();
};

template<UpdatesMetrics List, HasSnapshot Item>
requires HasExernalGarbageCollection<List>
struct ListOfLists {
std::shared_ptr<Metrics> metrics;

Expand Down Expand Up @@ -80,7 +85,22 @@ struct ListOfLists {
auto guard = std::lock_guard(_mutex);
metrics = new_metrics;
}
// void run_external_cleanup() noexcept;

/**
Runs an external clean up.
*/
void run_external_cleanup() noexcept {
auto lists = [&] {
auto guard = std::lock_guard(_mutex);
return _lists;
}();

for (auto& weak_list : lists) {
if (auto list = weak_list.lock()) {
list->garbage_collect_external();
}
}
}
};

} // namespace arangodb::containers
20 changes: 19 additions & 1 deletion tests/Containers/Concurrent/ListOfListsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
///
/// @author Julia Volmer
////////////////////////////////////////////////////////////////////////////////
#include "Containers/Concurrent/ListOfThreadOwnedLists.h"
#include "Containers/Concurrent/ListOfLists.h"

#include <gtest/gtest.h>
#include <memory>
Expand Down Expand Up @@ -48,6 +48,7 @@ struct MyMetrics : Metrics {
struct MyNodeList {
std::vector<MyData> data;
std::shared_ptr<Metrics> metrics;
bool isGarbageCollected = false;

MyNodeList(std::vector<MyData> data) : data{std::move(data)} {
if (metrics) {
Expand All @@ -70,6 +71,8 @@ struct MyNodeList {
auto set_metrics(std::shared_ptr<Metrics> new_metrics) -> void {
metrics = new_metrics;
}

auto garbage_collect_external() -> void { isGarbageCollected = true; }
};

using MyList = ListOfLists<MyNodeList, MyData>;
Expand Down Expand Up @@ -135,3 +138,18 @@ TEST(ListOfListsTest, uses_list_of_lists_metrics_for_all_lists) {
EXPECT_EQ(newMetrics->lists, 2);
EXPECT_EQ(dynamic_cast<MyMetrics*>(list.metrics.get())->lists, 2);
}

TEST(ListOfListsTest, executes_garbage_collection_on_each_list) {
MyList list;
auto first_inner_list =
std::make_shared<MyNodeList>(std::vector<MyData>{1, 2, 3});
auto second_inner_list =
std::make_shared<MyNodeList>(std::vector<MyData>{4, 5, 6});
list.add(first_inner_list);
list.add(second_inner_list);

list.run_external_cleanup();

EXPECT_TRUE(first_inner_list->isGarbageCollected);
EXPECT_TRUE(second_inner_list->isGarbageCollected);
}
0