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();
346 T& operator*() const noexcept {
return *accessors<T>::to_value(_p); }
347 T* operator->() const noexcept {
return accessors<T>::to_value(_p); }
348 T* get() const noexcept {
350 return accessors<T>::to_value(_p);
364 std::unique_ptr<T, disposer> release() noexcept {
365 auto p = std::exchange(_p,
nullptr);
369 return std::unique_ptr<T, disposer>(accessors<T>::to_value(p));
373 long int use_count() const noexcept {
381 operator lw_shared_ptr<const T>() const noexcept {
382 return lw_shared_ptr<const T>(_p);
385 explicit operator bool() const noexcept {
389 bool owned() const noexcept {
390 return _p->_count == 1;
393 bool operator==(
const lw_shared_ptr<const T>& x)
const {
397 bool operator!=(
const lw_shared_ptr<const T>& x)
const {
398 return !operator==(x);
401 bool operator==(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
405 bool operator!=(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
406 return !operator==(x);
409 bool operator<(
const lw_shared_ptr<const T>& x)
const {
413 bool operator<(
const lw_shared_ptr<std::remove_const_t<T>>& x)
const {
417 template <
typename U>
418 friend class lw_shared_ptr;
420 template <
typename X,
typename... A>
421 friend lw_shared_ptr<X> make_lw_shared(A&&...);
423 template <
typename U>
424 friend lw_shared_ptr<U> make_lw_shared(U&&);
426 template <
typename U>
427 friend lw_shared_ptr<U> make_lw_shared(U&);
429 template <
typename U>
430 friend class enable_lw_shared_from_this;
433template <
typename T,
typename... A>
435lw_shared_ptr<T> make_lw_shared(A&&... a) {
436 return lw_shared_ptr<T>::make(std::forward<A>(a)...);
441lw_shared_ptr<T> make_lw_shared(T&& a) {
442 return lw_shared_ptr<T>::make(std::move(a));
447lw_shared_ptr<T> make_lw_shared(T& a) {
448 return lw_shared_ptr<T>::make(a);
450SEASTAR_MODULE_EXPORT_END
455enable_lw_shared_from_this<T>::shared_from_this() noexcept {
456 return lw_shared_ptr<T>(
this);
461lw_shared_ptr<const T>
462enable_lw_shared_from_this<T>::shared_from_this() const noexcept {
463 return lw_shared_ptr<const T>(
const_cast<enable_lw_shared_from_this*
>(
this));
469std::ostream& operator<<(std::ostream& out,
const lw_shared_ptr<T>& p) {
471 return out <<
"null";
481 shared_ptr_counter_type count = 0;
487 template <
typename... A>
491SEASTAR_MODULE_EXPORT_BEGIN
497 long use_count()
const noexcept {
return count; }
499 template <
typename U>
502 template <
typename U,
bool esft>
509 mutable T* _p =
nullptr;
525 using element_type = T;
542 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
550 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
558#pragma GCC diagnostic push
559#ifdef SEASTAR_IGNORE_USE_AFTER_FREE
560#pragma GCC diagnostic ignored "-Wuse-after-free"
562 if (_b && !--_b->count) {
565#pragma GCC diagnostic pop
581 shared_ptr& operator=(std::nullptr_t)
noexcept {
584 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
592 template <
typename U,
typename = std::enable_if_t<std::is_base_of_v<T, U>>>
600 explicit operator bool()
const noexcept {
603 T& operator*()
const noexcept {
606 T* operator->()
const noexcept {
609 T* get()
const noexcept {
612 long use_count()
const noexcept {
623 template <
typename U,
typename... A>
626 template <
typename U>
629 template <
typename V,
typename U>
632 template <
typename V,
typename U>
635 template <
typename V,
typename U>
638 template <
bool esft,
typename... A>
641 template <
typename U>
644 template <
typename U,
bool esft>
647 template <
typename U>
650SEASTAR_MODULE_EXPORT_END
652template <
typename U,
bool esft>
657 template <
typename... A>
665 template <
typename... A>
667 auto p =
new T(std::forward<A>(a)...);
672SEASTAR_MODULE_EXPORT_BEGIN
673template <
typename T,
typename... A>
676make_shared(A&&... a) {
678 return helper::make(std::forward<A>(a)...);
685 using helper = shared_ptr_make_helper<T, std::is_base_of_v<shared_ptr_count_base, T>>;
686 return helper::make(std::forward<T>(a));
689template <
typename T,
typename U>
692static_pointer_cast(
const shared_ptr<U>& p) {
693 return shared_ptr<T>(p._b,
static_cast<T*
>(p._p));
696template <
typename T,
typename U>
699dynamic_pointer_cast(
const shared_ptr<U>& p) {
700 auto q =
dynamic_cast<T*
>(p._p);
701 return shared_ptr<T>(q ? p._b :
nullptr, q);
704template <
typename T,
typename U>
707const_pointer_cast(
const shared_ptr<U>& p) {
708 return shared_ptr<T>(p._b,
const_cast<T*
>(p._p));
710SEASTAR_MODULE_EXPORT_END
715enable_shared_from_this<T>::shared_from_this() noexcept {
716 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(
this);
717 return shared_ptr<T>(unconst);
723enable_shared_from_this<T>::shared_from_this() const noexcept {
724 auto esft =
const_cast<enable_shared_from_this*
>(
this);
725 auto unconst =
reinterpret_cast<enable_shared_from_this<std::remove_const_t<T>
>*>(esft);
726 return shared_ptr<const T>(unconst);
729SEASTAR_MODULE_EXPORT_BEGIN
730template <
typename T,
typename U>
733operator==(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
734 return x.get() == y.get();
740operator==(
const shared_ptr<T>& x, std::nullptr_t) {
741 return x.get() ==
nullptr;
747operator==(std::nullptr_t,
const shared_ptr<T>& y) {
748 return nullptr == y.get();
754operator==(
const lw_shared_ptr<T>& x, std::nullptr_t) {
755 return x.get() ==
nullptr;
761operator==(std::nullptr_t,
const lw_shared_ptr<T>& y) {
762 return nullptr == y.get();
765template <
typename T,
typename U>
768operator!=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
769 return x.get() != y.get();
775operator!=(
const shared_ptr<T>& x, std::nullptr_t) {
776 return x.get() !=
nullptr;
782operator!=(std::nullptr_t,
const shared_ptr<T>& y) {
783 return nullptr != y.get();
789operator!=(
const lw_shared_ptr<T>& x, std::nullptr_t) {
790 return x.get() !=
nullptr;
796operator!=(std::nullptr_t,
const lw_shared_ptr<T>& y) {
797 return nullptr != y.get();
800template <
typename T,
typename U>
803operator<(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
804 return x.get() < y.get();
810operator<(
const shared_ptr<T>& x, std::nullptr_t) {
811 return x.get() <
nullptr;
817operator<(std::nullptr_t,
const shared_ptr<T>& y) {
818 return nullptr < y.get();
821template <
typename T,
typename U>
824operator<=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
825 return x.get() <= y.get();
831operator<=(
const shared_ptr<T>& x, std::nullptr_t) {
832 return x.get() <=
nullptr;
838operator<=(std::nullptr_t,
const shared_ptr<T>& y) {
839 return nullptr <= y.get();
842template <
typename T,
typename U>
845operator>(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
846 return x.get() > y.get();
852operator>(
const shared_ptr<T>& x, std::nullptr_t) {
853 return x.get() >
nullptr;
859operator>(std::nullptr_t,
const shared_ptr<T>& y) {
860 return nullptr > y.get();
863template <
typename T,
typename U>
866operator>=(
const shared_ptr<T>& x,
const shared_ptr<U>& y) {
867 return x.get() >= y.get();
873operator>=(
const shared_ptr<T>& x, std::nullptr_t) {
874 return x.get() >=
nullptr;
880operator>=(std::nullptr_t,
const shared_ptr<T>& y) {
881 return nullptr >= y.get();
886std::ostream& operator<<(std::ostream& out,
const shared_ptr<T>& p) {
888 return out <<
"null";
894using shared_ptr_equal_by_value = indirect_equal_to<shared_ptr<T>>;
897using shared_ptr_value_hash = indirect_hash<shared_ptr<T>>;
899SEASTAR_MODULE_EXPORT_END
906struct hash<
seastar::lw_shared_ptr<T>> :
private hash<T*> {
908 return hash<T*>::operator()(p.get());
914struct hash<
seastar::shared_ptr<T>> :
private hash<T*> {
916 return hash<T*>::operator()(p.get());
937 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
940 return fmt::format_to(ctx.out(),
"null");
942 return fmt::format_to(ctx.out(),
"{}", *p);
948 constexpr auto parse(format_parse_context& ctx) {
return ctx.begin(); }
951 return fmt::format_to(ctx.out(),
"null");
953 return fmt::format_to(ctx.out(),
"{}", *p);
Definition: shared_ptr.hh:148
Definition: shared_ptr.hh:493
Definition: shared_ptr.hh:295
Definition: shared_ptr.hh:268
Definition: shared_ptr.hh:507
Definition: shared_ptr.hh:621
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
Definition: shared_ptr.hh:197
Definition: shared_ptr.hh:653
Definition: is_smart_ptr.hh:30
Definition: shared_ptr.hh:107
Definition: shared_ptr.hh:170
Definition: shared_ptr.hh:478
Definition: shared_ptr.hh:485