Skip to content

Commit

Permalink
add non-working test with reentrant deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
martinus committed Oct 5, 2024
1 parent 064a245 commit 69ce5f4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
4 changes: 4 additions & 0 deletions test/app/counter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ auto counter::obj::get() const -> size_t const& {
return m_data;
}

auto counter::obj::counts() -> counter& {
return *m_counts;
}

auto counter::obj::get() -> size_t& {
if (nullptr != m_counts) {
++m_counts->m_data.m_get;
Expand Down
2 changes: 2 additions & 0 deletions test/app/counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class counter {
[[nodiscard]] auto get() const -> size_t const&;
auto get() -> size_t&;

[[nodiscard]] auto counts() -> counter&;

void swap(obj& other);
[[nodiscard]] auto get_for_hash() const -> size_t;

Expand Down
45 changes: 27 additions & 18 deletions test/unit/reentrant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,42 @@
#include <app/counter.h>
#include <app/doctest.h>

TEST_CASE_MAP("reentrant_destruct", counter::obj, counter::obj) {
auto counts = counter{};
INFO(counts);
namespace {

auto container = typename map_t::value_container_type{};
class EraseOnDestruct;

// TODO
using map_t = ankerl::unordered_dense::map<counter::obj, std::unique_ptr<EraseOnDestruct>>;

for (size_t i = 0; i < 100; ++i) {
container.emplace_back(counter::obj{i, counts}, counter::obj{i, counts});
container.emplace_back(counter::obj{i, counts}, counter::obj{i, counts});
}
class EraseOnDestruct {
map_t* m_map;
counter::obj m_counter;

public:
EraseOnDestruct(map_t& map, size_t i, counter& counts)
: m_map(&map)
, m_counter(i, counts) {}

for (size_t i = 0; i < 10; ++i) {
container.emplace_back(counter::obj{i, counts}, counter::obj{i, counts});
~EraseOnDestruct() {
(void)m_map;
m_map->erase(counter::obj{m_counter.get() + 1, m_counter.counts()});
}
};

} // namespace

TEST_CASE("reentrant_destruct") {
auto counts = counter{};
INFO(counts);

// add some elements
auto map = map_t();
for (size_t i = 0; i < 10; ++i) {
map.try_emplace(counter::obj{i, counts}, counter::obj{i, counts});
}

map.replace(std::move(container));
/*
This doesn't work, it is not something that can be supported with using std::vector.
I'll leave the code here so it's not lost though.
REQUIRE(map.size() == 100U);
for (size_t i = 0; i < 100; ++i) {
REQUIRE(map.contains(counter::obj{i, counts}));
map.try_emplace(counter::obj{i, counts}, std::make_unique<EraseOnDestruct>(map, i, counts));
}
map.erase(counter::obj{0, counts});
*/
}

0 comments on commit 69ce5f4

Please sign in to comment.