From d11a8248cfd0c8f14cd10750ceec9326e1fdbee5 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Thu, 1 Mar 2018 15:53:23 +0800 Subject: [PATCH] msg/async/dpdk/shared_ptr.h: sync up with seastar impl otherwise the dpdk plugin does not compile. * remove workarounds for C++11. for example, std::void_t is available in C++17 now. * drop seastar::shared_ptr<>, as it's not used in async/dpdk now. * update the editor variable to match seastar's coding style Signed-off-by: Kefu Chai --- src/msg/async/dpdk/shared_ptr.h | 387 +++++++++++++++++++++----------- 1 file changed, 256 insertions(+), 131 deletions(-) diff --git a/src/msg/async/dpdk/shared_ptr.h b/src/msg/async/dpdk/shared_ptr.h index 11fbf2c90582a..382cda6b2dfe3 100644 --- a/src/msg/async/dpdk/shared_ptr.h +++ b/src/msg/async/dpdk/shared_ptr.h @@ -1,4 +1,4 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// -*- mode:C++; tab-width:8; c-basic-offset:4; indent-tabs-mode:nil -*- /* * This file is open source software, licensed to you under the terms * of the Apache License, Version 2.0 (the "License"). See the NOTICE file @@ -28,10 +28,10 @@ #include #include -// This header defines two shared pointer facilities, lw_shared_ptr<> +// This header defines a shared pointer facility, lw_shared_ptr<>, // modeled after std::shared_ptr<>. // -// Unlike std::shared_ptr<>, neither of these implementations are thread +// Unlike std::shared_ptr<>, this implementation is thread // safe, and two pointers sharing the same object must not be used in // different threads. // @@ -39,16 +39,19 @@ // occupying just one machine word, and adding just one word to the shared // object. However, it does not support polymorphism. // -// Both variants support shared_from_this() via enable_shared_from_this<> +// It supports shared_from_this() via enable_shared_from_this<> // and lw_enable_shared_from_this<>(). // -template< class T > -using remove_const_t = typename remove_const::type; - template class lw_shared_ptr; +template +class enable_lw_shared_from_this; + +template +class enable_shared_from_this; + template lw_shared_ptr make_lw_shared(A&&... a); @@ -58,157 +61,279 @@ lw_shared_ptr make_lw_shared(T&& a); template lw_shared_ptr make_lw_shared(T& a); +struct lw_shared_ptr_counter_base { + long _count = 0; +}; + + +namespace internal { + +template +struct lw_shared_ptr_accessors; + +template +struct lw_shared_ptr_accessors_esft; + +template +struct lw_shared_ptr_accessors_no_esft; + +} + + +// We want to support two use cases for shared_ptr: +// +// 1. T is any type (primitive or class type) +// +// 2. T is a class type that inherits from enable_shared_from_this. +// +// In the first case, we must wrap T in an object containing the counter, +// since T may be a primitive type and cannot be a base class. +// +// In the second case, we want T to reach the counter through its +// enable_shared_from_this<> base class, so that we can implement +// shared_from_this(). +// +// To implement those two conflicting requirements (T alongside its counter; +// T inherits from an object containing the counter) we use std::conditional<> +// and some accessor functions to select between two implementations. + + // CRTP from this to enable shared_from_this: template -class enable_lw_shared_from_this { - long _count = 0; - using ctor = T; - T* to_value() { return static_cast(this); } - T* to_internal_object() { return static_cast(this); } - protected: - enable_lw_shared_from_this() noexcept {} - enable_lw_shared_from_this(enable_lw_shared_from_this&&) noexcept {} - enable_lw_shared_from_this(const enable_lw_shared_from_this&) noexcept {} - enable_lw_shared_from_this& operator=(const enable_lw_shared_from_this&) noexcept { return *this; } - enable_lw_shared_from_this& operator=(enable_lw_shared_from_this&&) noexcept { return *this; } - public: - lw_shared_ptr shared_from_this(); - lw_shared_ptr shared_from_this() const; - template - friend class lw_shared_ptr; +class enable_lw_shared_from_this : private lw_shared_ptr_counter_base { + using ctor = T; +protected: + enable_lw_shared_from_this() noexcept {} + enable_lw_shared_from_this(enable_lw_shared_from_this&&) noexcept {} + enable_lw_shared_from_this(const enable_lw_shared_from_this&) noexcept {} + enable_lw_shared_from_this& operator=(const enable_lw_shared_from_this&) noexcept { return *this; } + enable_lw_shared_from_this& operator=(enable_lw_shared_from_this&&) noexcept { return *this; } +public: + lw_shared_ptr shared_from_this(); + lw_shared_ptr shared_from_this() const; + + template + friend class lw_shared_ptr; + template + friend class internal::lw_shared_ptr_accessors_esft; + template + friend class internal::lw_shared_ptr_accessors; }; template -struct shared_ptr_no_esft { - T _value; - using ctor = shared_ptr_no_esft; - - T* to_value() { return &_value; } - shared_ptr_no_esft* to_internal_object() { return this; } - shared_ptr_no_esft() = default; - shared_ptr_no_esft(const T& x) : _value(x) {} - shared_ptr_no_esft(T&& x) : _value(std::move(x)) {} - template - shared_ptr_no_esft(A&&... a) : _value(std::forward(a)...) {} - template - friend class lw_shared_ptr; +struct shared_ptr_no_esft : private lw_shared_ptr_counter_base { + T _value; + + shared_ptr_no_esft() = default; + shared_ptr_no_esft(const T& x) : _value(x) {} + shared_ptr_no_esft(T&& x) : _value(std::move(x)) {} + template + shared_ptr_no_esft(A&&... a) : _value(std::forward(a)...) {} + + template + friend class lw_shared_ptr; + template + friend class internal::lw_shared_ptr_accessors_no_esft; + template + friend class internal::lw_shared_ptr_accessors; }; + +/// Extension point: the user may override this to change how \ref lw_shared_ptr objects are destroyed, +/// primarily so that incomplete classes can be used. +/// +/// Customizing the deleter requires that \c T be derived from \c enable_lw_shared_from_this. +/// The specialization must be visible for all uses of \c lw_shared_ptr. +/// +/// To customize, the template must have a `static void dispose(T*)` operator that disposes of +/// the object. +template +struct lw_shared_ptr_deleter; // No generic implementation + +namespace internal { + template -using shared_ptr_impl = typename std::conditional< - std::is_base_of>, T>::value, - enable_lw_shared_from_this>, - shared_ptr_no_esft> >::type; +struct lw_shared_ptr_accessors_esft { + using concrete_type = std::remove_const_t; + static T* to_value(lw_shared_ptr_counter_base* counter) { + return static_cast(counter); + } + static void dispose(lw_shared_ptr_counter_base* counter) { + delete static_cast(counter); + } + static void instantiate_to_value(lw_shared_ptr_counter_base* p) { + // since to_value() is defined above, we don't need to do anything special + // to force-instantiate it + } +}; + +template +struct lw_shared_ptr_accessors_no_esft { + using concrete_type = shared_ptr_no_esft; + static T* to_value(lw_shared_ptr_counter_base* counter) { + return &static_cast(counter)->_value; + } + static void dispose(lw_shared_ptr_counter_base* counter) { + delete static_cast(counter); + } + static void instantiate_to_value(lw_shared_ptr_counter_base* p) { + // since to_value() is defined above, we don't need to do anything special + // to force-instantiate it + } +}; + +// Generic case: lw_shared_ptr_deleter is not specialized, select +// implementation based on whether T inherits from enable_lw_shared_from_this. +template +struct lw_shared_ptr_accessors : std::conditional_t< + std::is_base_of, T>::value, + lw_shared_ptr_accessors_esft, + lw_shared_ptr_accessors_no_esft> { +}; + +// Overload when lw_shared_ptr_deleter specialized +template +struct lw_shared_ptr_accessors{})>> { + using concrete_type = T; + static T* to_value(lw_shared_ptr_counter_base* counter); + static void dispose(lw_shared_ptr_counter_base* counter) { + lw_shared_ptr_deleter::dispose(to_value(counter)); + } + static void instantiate_to_value(lw_shared_ptr_counter_base* p) { + // instantiate to_value(); must be defined by shared_ptr_incomplete.hh + to_value(p); + } +}; + +} template class lw_shared_ptr { - mutable shared_ptr_impl* _p = nullptr; - private: - lw_shared_ptr(shared_ptr_impl* p) noexcept : _p(p) { - if (_p) { - ++_p->_count; + using accessors = internal::lw_shared_ptr_accessors>; + using concrete_type = typename accessors::concrete_type; + mutable lw_shared_ptr_counter_base* _p = nullptr; +private: + lw_shared_ptr(lw_shared_ptr_counter_base* p) noexcept : _p(p) { + if (_p) { + ++_p->_count; + } + } + template + static lw_shared_ptr make(A&&... a) { + auto p = new concrete_type(std::forward(a)...); + accessors::instantiate_to_value(p); + return lw_shared_ptr(p); + } +public: + using element_type = T; + + lw_shared_ptr() noexcept = default; + lw_shared_ptr(std::nullptr_t) noexcept : lw_shared_ptr() {} + lw_shared_ptr(const lw_shared_ptr& x) noexcept : _p(x._p) { + if (_p) { + ++_p->_count; + } + } + lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) { + x._p = nullptr; + } + [[gnu::always_inline]] + ~lw_shared_ptr() { + if (_p && !--_p->_count) { + accessors::dispose(_p); + } } - } - template - static lw_shared_ptr make(A&&... a) { - return lw_shared_ptr(new typename shared_ptr_impl::ctor(std::forward(a)...)); - } - public: - using element_type = T; - - lw_shared_ptr() noexcept = default; - lw_shared_ptr(std::nullptr_t) noexcept : lw_shared_ptr() {} - lw_shared_ptr(const lw_shared_ptr& x) noexcept : _p(x._p) { - if (_p) { - ++_p->_count; + lw_shared_ptr& operator=(const lw_shared_ptr& x) noexcept { + if (_p != x._p) { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(x); + } + return *this; } - } - lw_shared_ptr(lw_shared_ptr&& x) noexcept : _p(x._p) { - x._p = nullptr; - } - [[gnu::always_inline]] - ~lw_shared_ptr() { - if (_p && !--_p->_count) { - delete _p->to_internal_object(); + lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept { + if (_p != x._p) { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(std::move(x)); + } + return *this; } - } - lw_shared_ptr& operator=(const lw_shared_ptr& x) noexcept { - if (_p != x._p) { - this->~lw_shared_ptr(); - new (this) lw_shared_ptr(x); - } - return *this; - } - lw_shared_ptr& operator=(lw_shared_ptr&& x) noexcept { - if (_p != x._p) { - this->~lw_shared_ptr(); - new (this) lw_shared_ptr(std::move(x)); - } - return *this; - } - lw_shared_ptr& operator=(std::nullptr_t) noexcept { - return *this = lw_shared_ptr(); - } - lw_shared_ptr& operator=(T&& x) noexcept { - this->~lw_shared_ptr(); - new (this) lw_shared_ptr(make_lw_shared(std::move(x))); - return *this; - } - - T& operator*() const noexcept { return *_p->to_value(); } - T* operator->() const noexcept { return _p->to_value(); } - T* get() const noexcept { return _p->to_value(); } - - long int use_count() const noexcept { - if (_p) { - return _p->_count; - } else { - return 0; + lw_shared_ptr& operator=(std::nullptr_t) noexcept { + return *this = lw_shared_ptr(); + } + lw_shared_ptr& operator=(T&& x) noexcept { + this->~lw_shared_ptr(); + new (this) lw_shared_ptr(make_lw_shared(std::move(x))); + return *this; + } + + T& operator*() const noexcept { return *accessors::to_value(_p); } + T* operator->() const noexcept { return accessors::to_value(_p); } + T* get() const noexcept { + if (_p) { + return accessors::to_value(_p); + } else { + return nullptr; + } + } + + long int use_count() const noexcept { + if (_p) { + return _p->_count; + } else { + return 0; + } + } + + operator lw_shared_ptr() const noexcept { + return lw_shared_ptr(_p); + } + + explicit operator bool() const noexcept { + return _p; } - } - operator lw_shared_ptr() const noexcept { - return lw_shared_ptr(_p); - } + bool owned() const noexcept { + return _p->_count == 1; + } - explicit operator bool() const noexcept { - return _p; - } + bool operator==(const lw_shared_ptr& x) const { + return _p == x._p; + } - bool owned() const noexcept { - return _p->_count == 1; - } + bool operator!=(const lw_shared_ptr& x) const { + return !operator==(x); + } - bool operator==(const lw_shared_ptr& x) const { - return _p == x._p; - } + bool operator==(const lw_shared_ptr>& x) const { + return _p == x._p; + } - bool operator!=(const lw_shared_ptr& x) const { - return !operator==(x); - } + bool operator!=(const lw_shared_ptr>& x) const { + return !operator==(x); + } - bool operator==(const lw_shared_ptr>& x) const { - return _p == x._p; - } + bool operator<(const lw_shared_ptr& x) const { + return _p < x._p; + } - bool operator!=(const lw_shared_ptr>& x) const { - return !operator==(x); - } + bool operator<(const lw_shared_ptr>& x) const { + return _p < x._p; + } - template - friend class lw_shared_ptr; + template + friend class lw_shared_ptr; - template - friend lw_shared_ptr make_lw_shared(A&&...); + template + friend lw_shared_ptr make_lw_shared(A&&...); - template - friend lw_shared_ptr make_lw_shared(U&&); + template + friend lw_shared_ptr make_lw_shared(U&&); - template - friend lw_shared_ptr make_lw_shared(U&); + template + friend lw_shared_ptr make_lw_shared(U&); - template - friend class enable_lw_shared_from_this; + template + friend class enable_lw_shared_from_this; }; template -- 2.39.5