diff options
author | Håvard Pettersen <havardpe@yahooinc.com> | 2023-03-03 12:10:21 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@yahooinc.com> | 2023-03-03 12:10:21 +0000 |
commit | a738e084e5826ca3a4c420b1790330d94ce7147f (patch) | |
tree | 836339ade5160a86a6d8547cee0c52918e24d789 /vespalib/src | |
parent | 33ef2342e8369f471305c5cc63c61599d05b9705 (diff) |
fixup after review
Diffstat (limited to 'vespalib/src')
-rw-r--r-- | vespalib/src/tests/ref_counted/ref_counted_test.cpp | 12 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/ref_counted.h | 22 |
2 files changed, 23 insertions, 11 deletions
diff --git a/vespalib/src/tests/ref_counted/ref_counted_test.cpp b/vespalib/src/tests/ref_counted/ref_counted_test.cpp index 751d5b7c506..046823a9ebc 100644 --- a/vespalib/src/tests/ref_counted/ref_counted_test.cpp +++ b/vespalib/src/tests/ref_counted/ref_counted_test.cpp @@ -183,12 +183,24 @@ TEST(RefCountedTest, copy_ref_counted) { } } +struct Other : enable_ref_counted {}; + TEST(RefCountedTest, compile_errors_when_uncommented) { struct Foo {}; [[maybe_unused]] Foo foo; + [[maybe_unused]] ref_counted<Other> other = make_ref_counted<Other>(); // ref_counted<Foo> empty; // auto ref1 = make_ref_counted<Foo>(); // auto ref2 = ref_counted_from(foo); + // ref_counted<Base> base = other; +} + +TEST(RefCountedTest, self_assign) { + ref_counted<Leaf> ref = make_ref_counted<Leaf>(10); + ref = ref; + ref = std::move(ref); + EXPECT_EQ(ref->count_refs(), 1); + EXPECT_EQ(ref->val, 10); } TEST(RefCountedTest, with_threads) { diff --git a/vespalib/src/vespa/vespalib/util/ref_counted.h b/vespalib/src/vespa/vespalib/util/ref_counted.h index 6465a564891..ab0e1c82044 100644 --- a/vespalib/src/vespa/vespalib/util/ref_counted.h +++ b/vespalib/src/vespa/vespalib/util/ref_counted.h @@ -52,40 +52,40 @@ private: T *_ptr; ref_counted(T *ptr) noexcept : _ptr(ptr) {} void maybe_subref() noexcept { - if (_ptr) { + if (_ptr) [[likely]] { _ptr->internal_subref(); } } static T *maybe_addref(T *ptr) noexcept { - if (ptr) { + if (ptr) [[likely]] { ptr->internal_addref(); } return ptr; } + void replace_with(T *ptr) noexcept { + maybe_subref(); + _ptr = ptr; + } public: ref_counted() noexcept : _ptr(nullptr) {} ref_counted(ref_counted &&rhs) noexcept : _ptr(std::exchange(rhs._ptr, nullptr)) {} ref_counted(const ref_counted &rhs) noexcept : _ptr(maybe_addref(rhs._ptr)) {} ref_counted &operator=(ref_counted &&rhs) noexcept { - maybe_subref(); - _ptr = std::exchange(rhs._ptr, nullptr); + replace_with(std::exchange(rhs._ptr, nullptr)); return *this; } ref_counted &operator=(const ref_counted &rhs) noexcept { - maybe_subref(); - _ptr = maybe_addref(rhs._ptr); + replace_with(maybe_addref(rhs._ptr)); return *this; } template <typename X> ref_counted(ref_counted<X> &&rhs) noexcept : _ptr(std::exchange(rhs._ptr, nullptr)) {} template <typename X> ref_counted(const ref_counted<X> &rhs) noexcept : _ptr(maybe_addref(rhs._ptr)) {} template <typename X> ref_counted &operator=(ref_counted<X> &&rhs) noexcept { - maybe_subref(); - _ptr = std::exchange(rhs._ptr, nullptr); + replace_with(std::exchange(rhs._ptr, nullptr)); return *this; } template <typename X> ref_counted &operator=(const ref_counted<X> &rhs) noexcept { - maybe_subref(); - _ptr = maybe_addref(rhs._ptr); + replace_with(maybe_addref(rhs._ptr)); return *this; } T *operator->() const noexcept { return _ptr; } @@ -109,7 +109,7 @@ ref_counted<T> make_ref_counted(Args && ... args) { // create a new handle to a reference counted object // (NB: object must still be valid) template <typename T> -ref_counted<T> ref_counted_from(T &t) { +ref_counted<T> ref_counted_from(T &t) noexcept { t.internal_addref(); return ref_counted<T>::internal_attach(std::addressof(t)); } |