Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 2 additions & 59 deletions include/bitcoin/network/async/enable_shared_from_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,8 @@
namespace libbitcoin {
namespace network {

// "The constructors of std::shared_ptr detect the presence of an unambiguous
// and accessible (i.e. public inheritance is mandatory)
// enable_shared_from_this base and assign the newly created std::shared_ptr
// to weak-this if not already owned by a live std::shared_ptr.
// Constructing a std::shared_ptr for an object that is already managed by
// another std::shared_ptr will not consult weak-this and is undefined behavior.
// It is permitted to call shared_from_this only on a previously shared object,
// i.e. on an object managed by std::shared_ptr<T>. Otherwise,
// std::bad_weak_ptr is thrown(by the shared_ptr constructor).."
// en.cppreference.com/w/cpp/memory/enable_shared_from_this

/// Base instance must be downcastable to Derived.
/// Thread safe, base class.
/// Empty base optimization using CRTP.
/// Because enable_shared_from_this does not support inheritance.
template <class Base>
class enable_shared_from_base
Expand All @@ -52,53 +42,6 @@ class enable_shared_from_base
std::shared_ptr<Derived> shared_from_base() NOEXCEPT;
};

/// Sibling instance must be castable to Derived:Base.
/// Because enable_shared_from_this/base do not support multiple inheritance.
/// Avoids diamond inheritance ambiguity by requiring a primary inheritance
/// linear path (sibling) from which classes in an independent path (Base)
/// may obtain a shared pointer within their own path (Derived).
template <class Base, class Sibling>
class enable_shared_from_sibling
{
public:
DELETE_COPY_MOVE(enable_shared_from_sibling);

enable_shared_from_sibling() NOEXCEPT;

/// Must be a polymorphic type (to use dynamic_cast).
virtual ~enable_shared_from_sibling() NOEXCEPT;

/// Simplifies capture of the shared pointer for a nop handler.
void nop() volatile NOEXCEPT;

protected:
/// Sibling (not Derived:Base) implements enable_shared_from...
/// Use in Derived to create shared instance of Derived from its Sibling.
/// Undefined behavior if cast from Sibling* to Derived* not well formed.
template <class Derived, bc::if_base_of<Base, Derived> = true>
std::shared_ptr<Derived> shared_from_sibling() NOEXCEPT;
};

// class foo__ : enabled_shared_from_base<foo__>
// class foo_ : foo__
// class foo: foo_
// auto fooptr = foo.shared_from_this()
// auto foo_ptr = foo.shared_from_base<foo_>()
// auto foo__ptr = foo.shared_from_base<foo__>()
//
// class bar__ : enabled_shared_from_sibling<bar__, foo>
// class bar_ : bar__
// class bar : bar_
// bar__/bar_/bar must be joined with foo.
//
// class foobar : public foo, public bar
// auto barptr = foobar.shared_from_sibling<bar>()
// auto bar_ptr = foobar.shared_from_sibling<bar_>()
// auto bar__ptr = foobar.shared_from_sibling<bar__>()
// auto fooptr = foobar.shared_from_base<foo>()
// auto foo_ptr = foobar.shared_from_base<foo_>()
// auto foo__ptr = foobar.shared_from_base<foo__>()

} // namespace network
} // namespace libbitcoin

Expand Down
44 changes: 2 additions & 42 deletions include/bitcoin/network/impl/async/enable_shared_from_base.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,9 @@

namespace libbitcoin {
namespace network {

// enable_shared_from_base : enable_shared_from_this
// ----------------------------------------------------------------------------

template <class Base>
void enable_shared_from_base<Base>::
nop() volatile NOEXCEPT
void enable_shared_from_base<Base>::nop() volatile NOEXCEPT
{
}

Expand All @@ -39,44 +35,8 @@ template <class Derived, bc::if_base_of<Base, Derived>>
std::shared_ptr<Derived> enable_shared_from_base<Base>::
shared_from_base() NOEXCEPT
{
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
// Instance must be downcastable to Derived.
return std::static_pointer_cast<Derived>(this->shared_from_this());
BC_POP_WARNING()
}

// enable_shared_from_sibling
// ----------------------------------------------------------------------------

template <class Base, class Sibling>
enable_shared_from_sibling<Base, Sibling>::
enable_shared_from_sibling() NOEXCEPT
{
}

template <class Base, class Sibling>
enable_shared_from_sibling<Base, Sibling>::
~enable_shared_from_sibling() NOEXCEPT
{
}

template <class Base, class Sibling>
void enable_shared_from_sibling<Base, Sibling>::
nop() volatile NOEXCEPT
{
}

template <class Base, class Sibling>
template <class Derived, bc::if_base_of<Base, Derived>>
std::shared_ptr<Derived> enable_shared_from_sibling<Base, Sibling>::
shared_from_sibling() NOEXCEPT
{
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
// Obtain shared pointer to object from Sibling class inheritance path.
const auto sibling = dynamic_cast<Sibling*>(this)->shared_from_this();
BC_POP_WARNING()

// Cast pointer back to Derived (from Base) class it was created from.
return std::dynamic_pointer_cast<Derived>(sibling);
}

} // namespace network
Expand Down