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>
28 #ifndef SEASTAR_MODULE
29 #include <boost/intrusive/parent_from_member.hpp>
34 #include <type_traits>
38 #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)
41 #define SEASTAR_IGNORE_USE_AFTER_FREE
65 SEASTAR_MODULE_EXPORT_BEGIN
67 #ifndef SEASTAR_DEBUG_SHARED_PTR
68 using shared_ptr_counter_type = long;
70 using shared_ptr_counter_type = debug_shared_ptr_counter_type;
80 class enable_lw_shared_from_this;
83 class enable_shared_from_this;
85 template <
typename T,
typename... A>
86 lw_shared_ptr<T> make_lw_shared(A&&... a);
89 lw_shared_ptr<T> make_lw_shared(T&& a);
92 lw_shared_ptr<T> make_lw_shared(T& a);
94 template <
typename T,
typename... A>
95 shared_ptr<T> make_shared(A&&... a);
98 shared_ptr<T> make_shared(T&& a);
100 template <
typename T,
typename U>
101 shared_ptr<T> static_pointer_cast(
const shared_ptr<U>& p);
103 template <
typename T,
typename U>
104 shared_ptr<T> dynamic_pointer_cast(
const shared_ptr<U>& p);
106 template <
typename T,
typename U>
107 shared_ptr<T> const_pointer_cast(
const shared_ptr<U>& p);
110 shared_ptr_counter_type _count = 0;
113 SEASTAR_MODULE_EXPORT_END
117 template <
class T,
class U>
118 struct lw_shared_ptr_accessors;
121 struct lw_shared_ptr_accessors_esft;
124 struct lw_shared_ptr_accessors_no_esft;
148 SEASTAR_MODULE_EXPORT
149 template <
typename T>
161 long use_count()
const noexcept {
return _count; }
163 template <
typename X>
165 template <
typename X>
166 friend struct internal::lw_shared_ptr_accessors_esft;
167 template <
typename X,
class Y>
168 friend struct internal::lw_shared_ptr_accessors;
171 template <
typename T>
178 template <
typename... A>
181 template <
typename X>
183 template <
typename X>
184 friend struct internal::lw_shared_ptr_accessors_no_esft;
185 template <
typename X,
class Y>
186 friend struct internal::lw_shared_ptr_accessors;
198 template <
typename T>
203 template <
typename T>
204 struct lw_shared_ptr_accessors_esft {
205 using concrete_type = std::remove_const_t<T>;
207 return static_cast<T*
>(counter);
210 dispose(
static_cast<T*
>(counter));
212 static void dispose(T* value_ptr) {
215 static void instantiate_to_value(lw_shared_ptr_counter_base*) {
221 template <
typename T>
222 struct lw_shared_ptr_accessors_no_esft {
223 using concrete_type = lw_shared_ptr_no_esft<T>;
224 static T* to_value(lw_shared_ptr_counter_base* counter) {
225 return &
static_cast<concrete_type*
>(counter)->_value;
227 static void dispose(lw_shared_ptr_counter_base* counter) {
228 delete static_cast<concrete_type*
>(counter);
230 static void dispose(T* value_ptr) {
231 delete boost::intrusive::get_parent_from_member(value_ptr, &concrete_type::_value);
233 static void instantiate_to_value(lw_shared_ptr_counter_base*) {
241 template <
typename T,
typename U =
void>
242 struct lw_shared_ptr_accessors : std::conditional_t<
243 std::is_base_of_v<enable_lw_shared_from_this<T>, T>,
244 lw_shared_ptr_accessors_esft<T>,
245 lw_shared_ptr_accessors_no_esft<T>> {
249 template <
typename... T>
253 template <
typename T>
254 struct lw_shared_ptr_accessors<T, void_t<decltype(lw_shared_ptr_deleter<T>{})>> {
255 using concrete_type = T;
256 static T* to_value(lw_shared_ptr_counter_base* counter);
257 static void dispose(lw_shared_ptr_counter_base* counter) {
258 lw_shared_ptr_deleter<T>::dispose(to_value(counter));
260 static void instantiate_to_value(lw_shared_ptr_counter_base* p) {
268 SEASTAR_MODULE_EXPORT_BEGIN
269 template <
typename T>
271 template <
typename U>
272 using accessors = internal::lw_shared_ptr_accessors<std::remove_const_t<U>>;
281 template <
typename... A>
283 auto p =
new typename accessors<T>::concrete_type(std::forward<A>(a)...);
284 accessors<T>::instantiate_to_value(p);
288 using element_type = T;
292 static void dispose(T* p) noexcept {
293 accessors<T>::dispose(
const_cast<std::remove_const_t<T>*
>(p));
299 void operator()(T* p)
const noexcept {
308 #pragma GCC diagnostic push
309 #ifdef SEASTAR_IGNORE_USE_AFTER_FREE
310 #pragma GCC diagnostic ignored "-Wuse-after-free"
313 #pragma GCC diagnostic pop
316 lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) {
319 [[gnu::always_inline]]
321 #pragma GCC diagnostic push
322 #ifdef SEASTAR_IGNORE_USE_AFTER_FREE
323 #pragma GCC diagnostic ignored "-Wuse-after-free"
325 if (_p && !--_p->_count) {
326 accessors<T>::dispose(_p);
328 #pragma GCC diagnostic pop
330 lw_shared_ptr& operator=(
const lw_shared_ptr& x) noexcept {
332 this->~lw_shared_ptr();
333 new (
this) lw_shared_ptr(x);
337 lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept {
339 this->~lw_shared_ptr();
340 new (
this) lw_shared_ptr(std::move(x));
344 lw_shared_ptr& operator=(std::nullptr_t) noexcept {
345 return *
this = lw_shared_ptr();
347 [[deprecated(
"call make_lw_shared<> and assign the result instead")]]
348 lw_shared_ptr& operator=(T&& x) noexcept {
349 this->~lw_shared_ptr();
350 new (
this) lw_shared_ptr(make_lw_shared<T>(std::move(x)));
354 T& operator*() const noexcept {
return *accessors<T>::to_value(_p); }
355 T* operator->() const noexcept {
return accessors<T>::to_value(_p); }
356 T* get() const noexcept {
358 return accessors<T>::to_value(_p);
372 std::unique_ptr<T, disposer> release() noexcept {
373 auto p = std::exchange(_p,
nullptr);
377 return std::unique_ptr<T, disposer>(accessors<T>::to_value(p));
381 long int use_count() const noexcept {
389 operator lw_shared_ptr<const T>() const noexcept {
390 return lw_shared_ptr<const T>(_p);
393 explicit operator bool() const noexcept {
397 bool owned() const noexcept {
398 return _p->_count == 1;
401 bool operator==(
const lw_shared_ptr<const T>& x)
const {
405 bool operator!=(
const lw_shared_ptr<const T>& x)
const {
406 return !operator==(x);
409 bool operator==(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
413 bool operator!=(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
414 return !operator==(x);
417 bool operator<(
const lw_shared_ptr<const T>& x)
const {
421 bool operator<(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
425 template <
typename U>
426 friend class lw_shared_ptr;
428 template <
typename X,
typename... A>
429 friend lw_shared_ptr<X> make_lw_shared(A&&...);
431 template <
typename U>
432 friend lw_shared_ptr<U> make_lw_shared(U&&);
434 template <
typename U>
435 friend lw_shared_ptr<U> make_lw_shared(U&);
437 template <
typename U>
438 friend class enable_lw_shared_from_this;
441 template <
typename T,
typename... A>
443 lw_shared_ptr<T> make_lw_shared(A&&... a) {
444 return lw_shared_ptr<T>::make(std::forward<A>(a)...);
447 template <
typename T>
449 lw_shared_ptr<T> make_lw_shared(T&& a) {
450 return lw_shared_ptr<T>::make(std::move(a));
453 template <
typename T>
455 lw_shared_ptr<T> make_lw_shared(T& a) {
456 return lw_shared_ptr<T>::make(a);
458 SEASTAR_MODULE_EXPORT_END
460 template <
typename T>
463 enable_lw_shared_from_this<T>::shared_from_this() noexcept {
464 return lw_shared_ptr<T>(
this);
467 template <
typename T>
469 lw_shared_ptr<const T>
470 enable_lw_shared_from_this<T>::shared_from_this() const noexcept {
471 return lw_shared_ptr<const T>(
const_cast<enable_lw_shared_from_this*
>(
this));
474 SEASTAR_MODULE_EXPORT
475 template <
typename T>
477 std::ostream& operator<<(std::ostream& out,
const lw_shared_ptr<T>& p) {
479 return out <<
"null";
489 shared_ptr_counter_type count = 0;
492 template <
typename T>
495 template <
typename... A>
499 SEASTAR_MODULE_EXPORT_BEGIN
500 template <
typename T>
505 long use_count()
const noexcept {
return count; }
507 template <
typename U>
510 template <
typename U,
bool esft>
514 template <
typename T>
517 mutable T* _p =
nullptr;
533 using element_type = T;
550 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
558 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
566 #pragma GCC diagnostic push
567 #ifdef SEASTAR_IGNORE_USE_AFTER_FREE
568 #pragma GCC diagnostic ignored "-Wuse-after-free"
570 if (_b && !--_b->count) {
573 #pragma GCC diagnostic pop
589 shared_ptr& operator=(std::nullptr_t) noexcept {
592 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
600 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
608 explicit operator bool()
const noexcept {
611 T& operator*()
const noexcept {
614 T* operator->()
const noexcept {
617 T* get()
const noexcept {
620 long use_count()
const noexcept {
631 template <
typename U,
typename... A>
634 template <
typename U>
637 template <
typename V,
typename U>
640 template <
typename V,
typename U>
643 template <
typename V,
typename U>
646 template <
bool esft,
typename... A>
649 template <
typename U>
652 template <
typename U,
bool esft>
655 template <
typename U>
658 SEASTAR_MODULE_EXPORT_END
660 template <
typename U,
bool esft>
663 template <
typename T>
665 template <
typename... A>
671 template <
typename T>
673 template <
typename... A>
675 auto p =
new T(std::forward<A>(a)...);
680 SEASTAR_MODULE_EXPORT_BEGIN
681 template <
typename T,
typename... A>
684 make_shared(A&&... a) {
686 return helper::make(std::forward<A>(a)...);
689 template <
typename T>
693 using helper = shared_ptr_make_helper<T, std::is_base_of_v<shared_ptr_count_base, T>>;
694 return helper::make(std::forward<T>(a));
697 template <
typename T,
typename U>
700 static_pointer_cast(
const shared_ptr<U>& p) {
701 return shared_ptr<T>(p._b,
static_cast<T*
>(p._p));
704 template <
typename T,
typename U>
707 dynamic_pointer_cast(
const shared_ptr<U>& p) {
708 auto q =
dynamic_cast<T*
>(p._p);
709 return shared_ptr<T>(q ? p._b :
nullptr, q);
712 template <
typename T,
typename U>
715 const_pointer_cast(
const shared_ptr<U>& p) {
716 return shared_ptr<T>(p._b,
const_cast<T*
>(p._p));
718 SEASTAR_MODULE_EXPORT_END
720 template <
typename T>
723 enable_shared_from_this<T>::shared_from_this() noexcept {
724 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(
this);
725 return shared_ptr<T>(unconst);
728 template <
typename T>
731 enable_shared_from_this<T>::shared_from_this() const noexcept {
732 auto esft =
const_cast<enable_shared_from_this*
>(
this);
733 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(esft);
734 return shared_ptr<const T>(unconst);
737 SEASTAR_MODULE_EXPORT_BEGIN
738 template <
typename T,
typename U>
741 operator==(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
742 return x.get() == y.get();
745 template <
typename T>
748 operator==(
const shared_ptr<T>& x, std::nullptr_t) {
749 return x.get() ==
nullptr;
752 template <
typename T>
755 operator==(std::nullptr_t,
const shared_ptr<T>& y) {
756 return nullptr == y.get();
759 template <
typename T>
762 operator==(
const lw_shared_ptr<T>& x, std::nullptr_t) {
763 return x.get() ==
nullptr;
766 template <
typename T>
769 operator==(std::nullptr_t,
const lw_shared_ptr<T>& y) {
770 return nullptr == y.get();
773 template <
typename T,
typename U>
776 operator!=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
777 return x.get() != y.get();
780 template <
typename T>
783 operator!=(
const shared_ptr<T>& x, std::nullptr_t) {
784 return x.get() !=
nullptr;
787 template <
typename T>
790 operator!=(std::nullptr_t,
const shared_ptr<T>& y) {
791 return nullptr != y.get();
794 template <
typename T>
797 operator!=(
const lw_shared_ptr<T>& x, std::nullptr_t) {
798 return x.get() !=
nullptr;
801 template <
typename T>
804 operator!=(std::nullptr_t,
const lw_shared_ptr<T>& y) {
805 return nullptr != y.get();
808 template <
typename T,
typename U>
811 operator<(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
812 return x.get() < y.get();
815 template <
typename T>
818 operator<(
const shared_ptr<T>& x, std::nullptr_t) {
819 return x.get() <
nullptr;
822 template <
typename T>
825 operator<(std::nullptr_t,
const shared_ptr<T>& y) {
826 return nullptr < y.get();
829 template <
typename T,
typename U>
832 operator<=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
833 return x.get() <= y.get();
836 template <
typename T>
839 operator<=(
const shared_ptr<T>& x, std::nullptr_t) {
840 return x.get() <=
nullptr;
843 template <
typename T>
846 operator<=(std::nullptr_t,
const shared_ptr<T>& y) {
847 return nullptr <= y.get();
850 template <
typename T,
typename U>
853 operator>(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
854 return x.get() > y.get();
857 template <
typename T>
860 operator>(
const shared_ptr<T>& x, std::nullptr_t) {
861 return x.get() >
nullptr;
864 template <
typename T>
867 operator>(std::nullptr_t,
const shared_ptr<T>& y) {
868 return nullptr > y.get();
871 template <
typename T,
typename U>
874 operator>=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
875 return x.get() >= y.get();
878 template <
typename T>
881 operator>=(
const shared_ptr<T>& x, std::nullptr_t) {
882 return x.get() >=
nullptr;
885 template <
typename T>
888 operator>=(std::nullptr_t,
const shared_ptr<T>& y) {
889 return nullptr >= y.get();
892 template <
typename T>
894 std::ostream& operator<<(std::ostream& out,
const shared_ptr<T>& p) {
896 return out <<
"null";
902 using shared_ptr_equal_by_value = indirect_equal_to<shared_ptr<T>>;
905 using shared_ptr_value_hash = indirect_hash<shared_ptr<T>>;
907 SEASTAR_MODULE_EXPORT_END
912 SEASTAR_MODULE_EXPORT
913 template <
typename T>
914 struct hash<
seastar::lw_shared_ptr<T>> :
private hash<T*> {
916 return hash<T*>::operator()(p.get());
920 SEASTAR_MODULE_EXPORT
921 template <
typename T>
922 struct hash<
seastar::shared_ptr<T>> :
private hash<T*> {
924 return hash<T*>::operator()(p.get());
930 SEASTAR_MODULE_EXPORT
943 template <
typename T>
945 constexpr
auto parse(format_parse_context& ctx) {
return ctx.begin(); }
948 return fmt::format_to(ctx.out(),
"null");
950 return fmt::format_to(ctx.out(),
"{}", *p);
954 template <
typename T>
956 constexpr
auto parse(format_parse_context& ctx) {
return ctx.begin(); }
959 return fmt::format_to(ctx.out(),
"null");
961 return fmt::format_to(ctx.out(),
"{}", *p);
968 SEASTAR_MODULE_EXPORT
972 SEASTAR_MODULE_EXPORT
Definition: shared_ptr.hh:150
Definition: shared_ptr.hh:501
Definition: shared_ptr.hh:297
Definition: shared_ptr.hh:270
Definition: shared_ptr.hh:515
Definition: shared_ptr.hh:629
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: shared_ptr.hh:199
Definition: shared_ptr.hh:661
Definition: is_smart_ptr.hh:30
Definition: shared_ptr.hh:109
Definition: shared_ptr.hh:172
Definition: shared_ptr.hh:486
Definition: shared_ptr.hh:493