mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-29 20:57:00 +00:00
shared_ptr: fix reference count loss when creating a derived type with e_s_f_t
make_shared() has a special case for detecting a created class deriving
from enable_shared_from_this<>, so it can point the refcount pointer into
the object's data area instead of creating a shared_ptr_count_base for it.
The code, however, fails to detect a creating class deriving indirectly
from enable_shared_from_this:
struct base : enable_shared_from_this<base> {};
struct derived : base {};
make_shared<derived>(); // <- allocates independent refcount
The result is that the object reference counter lives in two locations.
Fix by detecting the derived class case as well.
This commit is contained in:
@@ -274,6 +274,9 @@ public:
|
|||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
friend class shared_ptr;
|
friend class shared_ptr;
|
||||||
|
|
||||||
|
template <typename U, bool esft>
|
||||||
|
friend struct shared_ptr_make_helper;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -418,7 +421,8 @@ template <typename T>
|
|||||||
struct shared_ptr_make_helper<T, true> {
|
struct shared_ptr_make_helper<T, true> {
|
||||||
template <typename... A>
|
template <typename... A>
|
||||||
static shared_ptr<T> make(A&&... a) {
|
static shared_ptr<T> make(A&&... a) {
|
||||||
return shared_ptr<T>(new T(std::forward<A>(a)...));
|
auto p = new T(std::forward<A>(a)...);
|
||||||
|
return shared_ptr<T>(p, p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -426,7 +430,7 @@ template <typename T, typename... A>
|
|||||||
inline
|
inline
|
||||||
shared_ptr<T>
|
shared_ptr<T>
|
||||||
make_shared(A&&... a) {
|
make_shared(A&&... a) {
|
||||||
using helper = shared_ptr_make_helper<T, std::is_base_of<enable_shared_from_this<T>, T>::value>;
|
using helper = shared_ptr_make_helper<T, std::is_base_of<shared_ptr_count_base, T>::value>;
|
||||||
return helper::make(std::forward<A>(a)...);
|
return helper::make(std::forward<A>(a)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +438,7 @@ template <typename T>
|
|||||||
inline
|
inline
|
||||||
shared_ptr<T>
|
shared_ptr<T>
|
||||||
make_shared(T&& a) {
|
make_shared(T&& a) {
|
||||||
using helper = shared_ptr_make_helper<T, std::is_base_of<enable_shared_from_this<T>, T>::value>;
|
using helper = shared_ptr_make_helper<T, std::is_base_of<shared_ptr_count_base, T>::value>;
|
||||||
return helper::make(std::forward<T>(a));
|
return helper::make(std::forward<T>(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user