aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@yahooinc.com>2023-03-03 12:10:21 +0000
committerHåvard Pettersen <havardpe@yahooinc.com>2023-03-03 12:10:21 +0000
commita738e084e5826ca3a4c420b1790330d94ce7147f (patch)
tree836339ade5160a86a6d8547cee0c52918e24d789 /vespalib
parent33ef2342e8369f471305c5cc63c61599d05b9705 (diff)
fixup after review
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/tests/ref_counted/ref_counted_test.cpp12
-rw-r--r--vespalib/src/vespa/vespalib/util/ref_counted.h22
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));
}