24#include <seastar/core/shared_ptr_debug_helper.hh>
25#include <seastar/util/is_smart_ptr.hh>
26#include <seastar/util/indirect.hh>
27#include <seastar/util/modules.hh>
29#include <boost/intrusive/parent_from_member.hpp>
36#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)
39#define SEASTAR_IGNORE_USE_AFTER_FREE
63SEASTAR_MODULE_EXPORT_BEGIN
65#ifndef SEASTAR_DEBUG_SHARED_PTR
66using shared_ptr_counter_type = long;
68using shared_ptr_counter_type = debug_shared_ptr_counter_type;
78class enable_lw_shared_from_this;
81class enable_shared_from_this;
83template <
typename T,
typename... A>
84lw_shared_ptr<T> make_lw_shared(A&&... a);
87lw_shared_ptr<T> make_lw_shared(T&& a);
90lw_shared_ptr<T> make_lw_shared(T& a);
92template <
typename T,
typename... A>
93shared_ptr<T> make_shared(A&&... a);
96shared_ptr<T> make_shared(T&& a);
98template <
typename T,
typename U>
99shared_ptr<T> static_pointer_cast(
const shared_ptr<U>& p);
101template <
typename T,
typename U>
102shared_ptr<T> dynamic_pointer_cast(
const shared_ptr<U>& p);
104template <
typename T,
typename U>
105shared_ptr<T> const_pointer_cast(
const shared_ptr<U>& p);
108 shared_ptr_counter_type _count = 0;
111SEASTAR_MODULE_EXPORT_END
115template <
class T,
class U>
116struct lw_shared_ptr_accessors;
119struct lw_shared_ptr_accessors_esft;
122struct lw_shared_ptr_accessors_no_esft;
159 long use_count()
const noexcept {
return _count; }
161 template <
typename X>
163 template <
typename X>
164 friend struct internal::lw_shared_ptr_accessors_esft;
165 template <
typename X,
class Y>
166 friend struct internal::lw_shared_ptr_accessors;
176 template <
typename... A>
179 template <
typename X>
181 template <
typename X>
182 friend struct internal::lw_shared_ptr_accessors_no_esft;
183 template <
typename X,
class Y>
184 friend struct internal::lw_shared_ptr_accessors;
202struct lw_shared_ptr_accessors_esft {
203 using concrete_type = std::remove_const_t<T>;
205 return static_cast<T*
>(counter);
208 dispose(
static_cast<T*
>(counter));
210 static void dispose(T* value_ptr) {
213 static void instantiate_to_value(lw_shared_ptr_counter_base*) {
220struct lw_shared_ptr_accessors_no_esft {
221 using concrete_type = lw_shared_ptr_no_esft<T>;
222 static T* to_value(lw_shared_ptr_counter_base* counter) {
223 return &
static_cast<concrete_type*
>(counter)->_value;
225 static void dispose(lw_shared_ptr_counter_base* counter) {
226 delete static_cast<concrete_type*
>(counter);
228 static void dispose(T* value_ptr) {
229 delete boost::intrusive::get_parent_from_member(value_ptr, &concrete_type::_value);
231 static void instantiate_to_value(lw_shared_ptr_counter_base*) {
239template <
typename T,
typename U =
void>
240struct lw_shared_ptr_accessors : std::conditional_t<
241 std::is_base_of_v<enable_lw_shared_from_this<T>, T>,
242 lw_shared_ptr_accessors_esft<T>,
243 lw_shared_ptr_accessors_no_esft<T>> {
247template <
typename... T>
252struct lw_shared_ptr_accessors<T, void_t<decltype(lw_shared_ptr_deleter<T>{})>> {
253 using concrete_type = T;
254 static T* to_value(lw_shared_ptr_counter_base* counter);
255 static void dispose(lw_shared_ptr_counter_base* counter) {
256 lw_shared_ptr_deleter<T>::dispose(to_value(counter));
258 static void instantiate_to_value(lw_shared_ptr_counter_base* p) {
266SEASTAR_MODULE_EXPORT_BEGIN
269 template <
typename U>
270 using accessors = internal::lw_shared_ptr_accessors<std::remove_const_t<U>>;
279 template <
typename... A>
281 auto p =
new typename accessors<T>::concrete_type(std::forward<A>(a)...);
282 accessors<T>::instantiate_to_value(p);
286 using element_type = T;
290 static void dispose(T* p)
noexcept {
291 accessors<T>::dispose(
const_cast<std::remove_const_t<T>*
>(p));
297 void operator()(T* p)
const noexcept {
306#pragma GCC diagnostic push
307#ifdef SEASTAR_IGNORE_USE_AFTER_FREE
308#pragma GCC diagnostic ignored "-Wuse-after-free"
311#pragma GCC diagnostic pop
314 lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) {
317 [[gnu::always_inline]]
319#pragma GCC diagnostic push
320#ifdef SEASTAR_IGNORE_USE_AFTER_FREE
321#pragma GCC diagnostic ignored "-Wuse-after-free"
323 if (_p && !--_p->_count) {
324 accessors<T>::dispose(_p);
326#pragma GCC diagnostic pop
328 lw_shared_ptr& operator=(
const lw_shared_ptr& x)
noexcept {
330 this->~lw_shared_ptr();
331 new (
this) lw_shared_ptr(x);
335 lw_shared_ptr& operator=(lw_shared_ptr&& x)
noexcept {
337 this->~lw_shared_ptr();
338 new (
this) lw_shared_ptr(std::move(x));
342 lw_shared_ptr& operator=(std::nullptr_t)
noexcept {
343 return *
this = lw_shared_ptr();
345 [[deprecated(
"call make_lw_shared<> and assign the result instead")]]
346 lw_shared_ptr& operator=(T&& x)
noexcept {
347 this->~lw_shared_ptr();
348 new (
this) lw_shared_ptr(make_lw_shared<T>(std::move(x)));
352 T& operator*() const noexcept {
return *accessors<T>::to_value(_p); }
353 T* operator->() const noexcept {
return accessors<T>::to_value(_p); }
354 T* get() const noexcept {
356 return accessors<T>::to_value(_p);
370 std::unique_ptr<T, disposer> release() noexcept {
371 auto p = std::exchange(_p,
nullptr);
375 return std::unique_ptr<T, disposer>(accessors<T>::to_value(p));
379 long int use_count() const noexcept {
387 operator lw_shared_ptr<const T>() const noexcept {
388 return lw_shared_ptr<const T>(_p);
391 explicit operator bool() const noexcept {
395 bool owned() const noexcept {
396 return _p->_count == 1;
399 bool operator==(
const lw_shared_ptr<const T>& x)
const {
403 bool operator!=(
const lw_shared_ptr<const T>& x)
const {
404 return !operator==(x);
407 bool operator==(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
411 bool operator!=(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
412 return !operator==(x);
415 bool operator<(
const lw_shared_ptr<const T>& x)
const {
419 bool operator<(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
423 template <
typename U>
424 friend class lw_shared_ptr;
426 template <
typename X,
typename... A>
427 friend lw_shared_ptr<X> make_lw_shared(A&&...);
429 template <
typename U>
430 friend lw_shared_ptr<U> make_lw_shared(U&&);
432 template <
typename U>
433 friend lw_shared_ptr<U> make_lw_shared(U&);
435 template <
typename U>
436 friend class enable_lw_shared_from_this;
439template <
typename T,
typename... A>
441lw_shared_ptr<T> make_lw_shared(A&&... a) {
442 return lw_shared_ptr<T>::make(std::forward<A>(a)...);
447lw_shared_ptr<T> make_lw_shared(T&& a) {
448 return lw_shared_ptr<T>::make(std::move(a));
453lw_shared_ptr<T> make_lw_shared(T& a) {
454 return lw_shared_ptr<T>::make(a);
456SEASTAR_MODULE_EXPORT_END
461enable_lw_shared_from_this<T>::shared_from_this() noexcept {
462 return lw_shared_ptr<T>(
this);
467lw_shared_ptr<const T>
468enable_lw_shared_from_this<T>::shared_from_this() const noexcept {
469 return lw_shared_ptr<const T>(
const_cast<enable_lw_shared_from_this*
>(
this));
475std::ostream& operator<<(std::ostream& out,
const lw_shared_ptr<T>& p) {
477 return out <<
"null";
487 shared_ptr_counter_type count = 0;
493 template <
typename... A>
497SEASTAR_MODULE_EXPORT_BEGIN
503 long use_count()
const noexcept {
return count; }
505 template <
typename U>
508 template <
typename U,
bool esft>
515 mutable T* _p =
nullptr;
531 using element_type = T;
548 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
556 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
564#pragma GCC diagnostic push
565#ifdef SEASTAR_IGNORE_USE_AFTER_FREE
566#pragma GCC diagnostic ignored "-Wuse-after-free"
568 if (_b && !--_b->count) {
571#pragma GCC diagnostic pop
587 shared_ptr& operator=(std::nullptr_t)
noexcept {
590 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
598 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
606 explicit operator bool()
const noexcept {
609 T& operator*()
const noexcept {
612 T* operator->()
const noexcept {
615 T* get()
const noexcept {
618 long use_count()
const noexcept {
629 template <
typename U,
typename... A>
632 template <
typename U>
635 template <
typename V,
typename U>
638 template <
typename V,
typename U>
641 template <
typename V,
typename U>
644 template <
bool esft,
typename... A>
647 template <
typename U>
650 template <
typename U,
bool esft>
653 template <
typename U>
656SEASTAR_MODULE_EXPORT_END
658template <
typename U,
bool esft>
663 template <
typename... A>
671 template <
typename... A>
673 auto p =
new T(std::forward<A>(a)...);
678SEASTAR_MODULE_EXPORT_BEGIN
679template <
typename T,
typename... A>
682make_shared(A&&... a) {
684 return helper::make(std::forward<A>(a)...);
691 using helper = shared_ptr_make_helper<T, std::is_base_of_v<shared_ptr_count_base, T>>;
692 return helper::make(std::forward<T>(a));
695template <
typename T,
typename U>
698static_pointer_cast(
const shared_ptr<U>& p) {
699 return shared_ptr<T>(p._b,
static_cast<T*
>(p._p));
702template <
typename T,
typename U>
705dynamic_pointer_cast(
const shared_ptr<U>& p) {
706 auto q =
dynamic_cast<T*
>(p._p);
707 return shared_ptr<T>(q ? p._b :
nullptr, q);
710template <
typename T,
typename U>
713const_pointer_cast(
const shared_ptr<U>& p) {
714 return shared_ptr<T>(p._b,
const_cast<T*
>(p._p));
716SEASTAR_MODULE_EXPORT_END
721enable_shared_from_this<T>::shared_from_this() noexcept {
722 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(
this);
723 return shared_ptr<T>(unconst);
729enable_shared_from_this<T>::shared_from_this() const noexcept {
730 auto esft =
const_cast<enable_shared_from_this*
>(
this);
731 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(esft);
732 return shared_ptr<const T>(unconst);
735SEASTAR_MODULE_EXPORT_BEGIN
736template <
typename T,
typename U>
739operator==(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
740 return x.get() == y.get();
746operator==(
const shared_ptr<T>& x, std::nullptr_t) {
747 return x.get() ==
nullptr;
753operator==(std::nullptr_t,
const shared_ptr<T>& y) {
754 return nullptr == y.get();
760operator==(
const lw_shared_ptr<T>& x, std::nullptr_t) {
761 return x.get() ==
nullptr;
767operator==(std::nullptr_t,
const lw_shared_ptr<T>& y) {
768 return nullptr == y.get();
771template <
typename T,
typename U>
774operator!=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
775 return x.get() != y.get();
781operator!=(
const shared_ptr<T>& x, std::nullptr_t) {
782 return x.get() !=
nullptr;
788operator!=(std::nullptr_t,
const shared_ptr<T>& y) {
789 return nullptr != y.get();
795operator!=(
const lw_shared_ptr<T>& x, std::nullptr_t) {
796 return x.get() !=
nullptr;
802operator!=(std::nullptr_t,
const lw_shared_ptr<T>& y) {
803 return nullptr != y.get();
806template <
typename T,
typename U>
809operator<(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
810 return x.get() < y.get();
816operator<(
const shared_ptr<T>& x, std::nullptr_t) {
817 return x.get() <
nullptr;
823operator<(std::nullptr_t,
const shared_ptr<T>& y) {
824 return nullptr < y.get();
827template <
typename T,
typename U>
830operator<=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
831 return x.get() <= y.get();
837operator<=(
const shared_ptr<T>& x, std::nullptr_t) {
838 return x.get() <=
nullptr;
844operator<=(std::nullptr_t,
const shared_ptr<T>& y) {
845 return nullptr <= y.get();
848template <
typename T,
typename U>
851operator>(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
852 return x.get() > y.get();
858operator>(
const shared_ptr<T>& x, std::nullptr_t) {
859 return x.get() >
nullptr;
865operator>(std::nullptr_t,
const shared_ptr<T>& y) {
866 return nullptr > y.get();
869template <
typename T,
typename U>
872operator>=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
873 return x.get() >= y.get();
879operator>=(
const shared_ptr<T>& x, std::nullptr_t) {
880 return x.get() >=
nullptr;
886operator>=(std::nullptr_t,
const shared_ptr<T>& y) {
887 return nullptr >= y.get();
892std::ostream& operator<<(std::ostream& out,
const shared_ptr<T>& p) {
894 return out <<
"null";
900using shared_ptr_equal_by_value = indirect_equal_to<shared_ptr<T>>;
903using shared_ptr_value_hash = indirect_hash<shared_ptr<T>>;
905SEASTAR_MODULE_EXPORT_END
912struct hash<
seastar::lw_shared_ptr<T>> :
private hash<T*> {
914 return hash<T*>::operator()(p.get());
920struct hash<
seastar::shared_ptr<T>> :
private hash<T*> {
922 return hash<T*>::operator()(p.get());
943 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
946 return fmt::format_to(ctx.out(),
"null");
948 return fmt::format_to(ctx.out(),
"{}", *p);
954 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
957 return fmt::format_to(ctx.out(),
"null");
959 return fmt::format_to(ctx.out(),
"{}", *p);
Definition: shared_ptr.hh:148
Definition: shared_ptr.hh:499
Definition: shared_ptr.hh:295
Definition: shared_ptr.hh:268
Definition: shared_ptr.hh:513
Definition: shared_ptr.hh:627
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: shared_ptr.hh:197
Definition: shared_ptr.hh:659
Definition: is_smart_ptr.hh:30
Definition: shared_ptr.hh:107
Definition: shared_ptr.hh:170
Definition: shared_ptr.hh:484
Definition: shared_ptr.hh:491