Skip to content

Instantly share code, notes, and snippets.

@eao197
Created April 23, 2019 06:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eao197/d094659467996207c39e68b61f25ee23 to your computer and use it in GitHub Desktop.
Save eao197/d094659467996207c39e68b61f25ee23 to your computer and use it in GitHub Desktop.
Полный код для статьи о деталях реализации message_holder_t из SObjectizer-5.6
template< typename Payload, typename Envelope >
class basic_message_holder_impl_t
{
protected :
intrusive_ptr_t< Envelope > m_msg;
public :
using payload_type = Payload;
using envelope_type = Envelope;
basic_message_holder_impl_t() noexcept = default;
basic_message_holder_impl_t( intrusive_ptr_t< Envelope > msg )
: m_msg{ std::move(msg) }
{}
void reset() noexcept { m_msg.reset(); }
[[nodiscard]]
bool empty() const noexcept { return static_cast<bool>( m_msg ); }
[[nodiscard]]
operator bool() const noexcept { return !this->empty(); }
[[nodiscard]]
bool operator!() const noexcept { return this->empty(); }
};
template< typename Payload, typename Envelope >
class shared_message_holder_impl_t
: public basic_message_holder_impl_t<Payload, Envelope>
{
using direct_base_type = basic_message_holder_impl_t<Payload, Envelope>;
public :
using direct_base_type::direct_base_type;
[[nodiscard]] intrusive_ptr_t< Envelope >
make_reference() const noexcept
{
return this->m_msg;
}
};
template< typename Payload, typename Envelope >
class unique_message_holder_impl_t
: public basic_message_holder_impl_t<Payload, Envelope>
{
using direct_base_type = basic_message_holder_impl_t<Payload, Envelope>;
public :
using direct_base_type::direct_base_type;
unique_message_holder_impl_t(
const unique_message_holder_impl_t & ) = delete;
unique_message_holder_impl_t(
unique_message_holder_impl_t && ) = default;
unique_message_holder_impl_t &
operator=( const unique_message_holder_impl_t & ) = delete;
unique_message_holder_impl_t &
operator=( unique_message_holder_impl_t && ) = default;
[[nodiscard]] intrusive_ptr_t< Envelope >
make_reference() noexcept
{
return { std::move(this->m_msg) };
}
};
template< typename Msg, message_ownership_t Ownership >
struct impl_selector
{
static_assert( !is_signal<Msg>::value,
"Signals can't be used with message_holder" );
using P = typename message_payload_type< Msg >::payload_type;
using E = typename message_payload_type< Msg >::envelope_type;
using type = std::conditional_t<
message_ownership_t::autodetected == Ownership,
std::conditional_t<
message_mutability_t::immutable_message ==
message_mutability_traits<Msg>::mutability,
shared_message_holder_impl_t<P, E>,
unique_message_holder_impl_t<P, E> >,
std::conditional_t<
message_ownership_t::shared == Ownership,
shared_message_holder_impl_t<P, E>,
unique_message_holder_impl_t<P, E> >
>;
};
template< typename Msg, message_ownership_t Ownership >
using impl_selector_t = typename impl_selector<Msg, Ownership>::type;
template< typename M >
M * get_ptr( const intrusive_ptr_t<M> & msg ) noexcept
{
return msg.get();
}
template< typename M >
M * get_ptr( const intrusive_ptr_t< user_type_message_t<M> > & msg ) noexcept
{
return std::addressof(msg->m_payload);
}
template< typename Base, typename Return_Type >
class msg_accessors_t : public Base
{
public :
using Base::Base;
[[nodiscard]] Return_Type *
get() const noexcept
{
return get_ptr( this->m_msg );
}
[[nodiscard]] Return_Type &
operator * () const noexcept { return *get(); }
[[nodiscard]] Return_Type *
operator->() const noexcept { return get(); }
};
template< message_mutability_t Mutability, typename Base >
struct accessor_selector
{
using type = std::conditional_t<
message_mutability_t::immutable_message == Mutability,
msg_accessors_t<Base, typename Base::payload_type const>,
msg_accessors_t<Base, typename Base::payload_type> >;
};
template< message_mutability_t Mutability, typename Base >
using accessor_selector_t = typename accessor_selector<Mutability, Base>::type;
template<
typename Msg,
message_ownership_t Ownership = message_ownership_t::autodetected >
class message_holder_t
: public details::message_holder_details::accessor_selector_t<
details::message_mutability_traits<Msg>::mutability,
details::message_holder_details::impl_selector_t<Msg, Ownership> >
{
using base_type = details::message_holder_details::accessor_selector_t<
details::message_mutability_traits<Msg>::mutability,
details::message_holder_details::impl_selector_t<Msg, Ownership> >;
public :
using payload_type = typename base_type::payload_type;
using envelope_type = typename base_type::envelope_type;
using base_type::base_type;
friend void
swap( message_holder_t & a, message_holder_t & b ) noexcept
{
using std::swap;
swap( a.m_msg, b.m_msg );
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment