diff --git a/include/crill/reclaim_object.h b/include/crill/reclaim_object.h index 401af4d..010f6e9 100644 --- a/include/crill/reclaim_object.h +++ b/include/crill/reclaim_object.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -61,50 +63,37 @@ class reclaim_object // Reading the value must happen through a reader class. class reader; - // read_ptr provides scoped read access to the value. - class read_ptr + // custom deleter for read-only unique_ptr + struct read_ptr_deleter { - public: - read_ptr(reader& rdr) noexcept - : rdr(rdr) + constexpr read_ptr_deleter() noexcept = default; + explicit constexpr read_ptr_deleter(reader& rdr) noexcept : rdr(&rdr) { assert(rdr.min_epoch == 0); - rdr.min_epoch.store(rdr.obj.current_epoch.load()); assert(rdr.min_epoch =! 0); + }; - value_read = rdr.obj.value.load(); - assert(value_read); - } - - ~read_ptr() - { - assert(rdr.min_epoch != 0); - rdr.min_epoch.store(0); - } + read_ptr_deleter(const read_ptr_deleter &) noexcept = default; + read_ptr_deleter(read_ptr_deleter &&) noexcept = default; + read_ptr_deleter &operator=(read_ptr_deleter const &) noexcept = default; + read_ptr_deleter &operator=(read_ptr_deleter &&) noexcept = default; - const T& operator*() const + void operator()(const T*) const { - assert(value_read); - return *value_read; + if (rdr) + { + assert(rdr->min_epoch != 0); + rdr->min_epoch.store(0); + } } - const T* operator->() const - { - assert(value_read); - return value_read; - } - - read_ptr(read_ptr&&) = delete; - read_ptr& operator=(read_ptr&&) = delete; - read_ptr(const read_ptr&) = delete; - read_ptr& operator=(const read_ptr&) = delete; - private: - reader& rdr; - T* value_read = nullptr; + reader* rdr; }; + using read_ptr = std::unique_ptr; + class reader { public: @@ -130,12 +119,13 @@ class reclaim_object // Non-blocking guarantees: wait-free. read_ptr read_lock() noexcept { - return read_ptr(*this); + auto deleter = read_ptr_deleter(*this); + return read_ptr(obj.value.load(), std::move(deleter)); } private: friend class reclaim_object; - friend class read_ptr; + friend class read_ptr_deleter; reclaim_object& obj; std::atomic min_epoch = 0; }; diff --git a/include/crill/reclaim_on_write_object.h b/include/crill/reclaim_on_write_object.h index 115cc33..6fe5757 100644 --- a/include/crill/reclaim_on_write_object.h +++ b/include/crill/reclaim_on_write_object.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include namespace crill { diff --git a/tests/reclaim_object_test.cpp b/tests/reclaim_object_test.cpp index c45ce81..753e93d 100644 --- a/tests/reclaim_object_test.cpp +++ b/tests/reclaim_object_test.cpp @@ -42,13 +42,18 @@ TEST_CASE("reclaim_object::read_ptr") crill::reclaim_object obj(3, 'x'); auto reader = obj.get_reader(); - SUBCASE("read_ptr is not copyable or movable") + SUBCASE("read_ptr is not copyable") { auto read_ptr = reader.read_lock(); static_assert(!std::is_copy_constructible_v); static_assert(!std::is_copy_assignable_v); - static_assert(!std::is_move_constructible_v); - static_assert(!std::is_move_assignable_v); + } + + SUBCASE("read_ptr is movable movable") + { + auto read_ptr = reader.read_lock(); + static_assert(std::is_move_constructible_v); + static_assert(std::is_move_assignable_v); } SUBCASE("Dereference") diff --git a/tests/utility_test.cpp b/tests/utility_test.cpp index 0b1d399..2fd6291 100644 --- a/tests/utility_test.cpp +++ b/tests/utility_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include "tests.h"