Skip to content

Commit

Permalink
The first step in implementation of #39.
Browse files Browse the repository at this point in the history
Possibility to specify custom_direct_mbox_factory added.
If custom_direct_mbox_factory is specified it's used for creation of the
direct mbox for an agent.
  • Loading branch information
eao197 committed Apr 22, 2022
1 parent 408b8b5 commit facfbfc
Show file tree
Hide file tree
Showing 12 changed files with 427 additions and 8 deletions.
50 changes: 47 additions & 3 deletions dev/so_5/agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,46 @@ state_t::handle_time_limit_on_exit() const
m_time_limit->drop_limit_for_agent( *m_target_agent, *this );
}

namespace
{

/*!
* \brief Helper for creation of the direct mbox for an agent.
*
* If there is a custom direct mbox factory in \a tuning_options
* then the return value of that factory is used. Otherwise the
* \a standard_mbox is returned.
*/
[[nodiscard]]
mbox_t
make_direct_mbox_with_respect_to_custom_factory(
partially_constructed_agent_ptr_t agent_ptr,
const agent_tuning_options_t & tuning_options,
mbox_t standard_mbox )
{
mbox_t result{ std::move(standard_mbox) };

const auto & factory =
tuning_options.query_custom_direct_mbox_factory();
if( factory )
{
result = factory( agent_ptr, std::move(result) );

if( mbox_type_t::multi_producer_single_consumer
!= result->type() )
{
SO_5_THROW_EXCEPTION(
rc_mpsc_mbox_expected,
"MPSC mbox is expected as the direct mbox "
"for an agent" );
}
}

return result;
}

} /* namespace anonymous */

//
// agent_t
//
Expand Down Expand Up @@ -501,9 +541,13 @@ agent_t::agent_t(
, m_env( ctx.env() )
, m_event_queue( nullptr )
, m_direct_mbox(
impl::internal_env_iface_t( ctx.env() ).create_mpsc_mbox(
self_ptr(),
m_message_limits.get() ) )
make_direct_mbox_with_respect_to_custom_factory(
partially_constructed_agent_ptr_t( self_ptr() ),
ctx.options(),
impl::internal_env_iface_t( ctx.env() ).create_mpsc_mbox(
self_ptr(),
m_message_limits.get() ) )
)
// It is necessary to enable agent subscription in the
// constructor of derived class.
, m_working_thread_id( so_5::query_current_thread_id() )
Expand Down
32 changes: 32 additions & 0 deletions dev/so_5/agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,38 @@ class SO_5_TYPE agent_t
return agent_tuning_options_t();
}

/*!
* \brief Helper for creation a custom direct mbox factory.
*
* Usage example:
* \code
* class my_agent : public so_5::agent_t {
* ...
* public:
* my_agent( context_t ctx )
* : so_5::agent_t{ ctx + custom_direct_mbox_factory(
* []( so_5::partially_constructed_agent_ptr_t agent_ptr,
* so_5::mbox_t actual_mbox )
* {
* return so_5::mbox_t{ new my_custom_mbox{ agent_ptr.ptr(), std::move(actual_mbox) } };
* } )
* }
* {...}
*
* ...
* };
* \endcode
*
* \since v.5.7.4
*/
template< typename Lambda >
[[nodiscard]]
custom_direct_mbox_factory_t
custom_direct_mbox_factory( Lambda && lambda )
{
return { std::forward<Lambda>(lambda) };
}

protected:
/*!
* \name Accessing the default state.
Expand Down
9 changes: 9 additions & 0 deletions dev/so_5/agent_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@ operator+(
ctx.options().priority( agent_priority );
return ctx;
}

inline agent_context_t
operator+(
agent_context_t ctx,
custom_direct_mbox_factory_t factory )
{
ctx.options().custom_direct_mbox_factory( std::move(factory) );
return ctx;
}
/*!
* \}
*/
Expand Down
87 changes: 82 additions & 5 deletions dev/so_5/agent_tuning_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,42 @@
namespace so_5
{

/*!
* \brief Wrapper around a pointer to partially constructed agent.
*
* This type is used as indicator that a pointer to agent can be
* transferred or stored somewhere, but shouldn't be used because
* the agent isn't fully constructed yet.
*
* \since v.5.7.4
*/
class partially_constructed_agent_ptr_t
{
agent_t * m_ptr;

public:
explicit partially_constructed_agent_ptr_t( agent_t * ptr )
: m_ptr{ ptr }
{}

[[nodiscard]]
agent_t *
ptr() const noexcept { return m_ptr; }
};

/*!
* \brief Type of functor to be used as a factory for custom direct mbox.
*
* \attention
* The factory should return a valid mbox or should throw an exception.
* The behavior isn't defined if the factory return empty so_5::mbox_t
* object (the application may crash in the better case).
*
* \since v.5.7.4
*/
using custom_direct_mbox_factory_t = std::function<
so_5::mbox_t(partially_constructed_agent_ptr_t, so_5::mbox_t) >;

//
// agent_tuning_options_t
//
Expand Down Expand Up @@ -87,33 +123,74 @@ class agent_tuning_options_t

//! Set priority for agent.
/*! \since
* v.5.5.8 */

* v.5.5.8
*/
agent_tuning_options_t &
priority( so_5::priority_t v )
{
m_priority = v;
return *this;
}

//FIXME: this method should be marked as [[nodiscard]] and
//noexcept in SO-5.8.
//! Get priority value.
so_5::priority_t
query_priority() const
{
return m_priority;
}

/*!
* \brief Set custom direct mbox factory.
*
* \since v.5.7.4
*/
agent_tuning_options_t &
custom_direct_mbox_factory(
custom_direct_mbox_factory_t factory )
{
m_custom_direct_mbox_factory = factory;

return *this;
}

/*!
* \brief Get a reference to custom direct mbox factory.
*
* \note
* If the factory isn't set then a reference to empty
* std::function object is returned.
*
* \since v.5.7.4
*/
[[nodiscard]]
const custom_direct_mbox_factory_t &
query_custom_direct_mbox_factory() const noexcept
{
return m_custom_direct_mbox_factory;
}

private :
subscription_storage_factory_t m_subscription_storage_factory =
default_subscription_storage_factory();

message_limit::description_container_t m_message_limits;

//! Priority for agent.
/*! \since
* v.5.5.8 */

/*!
* \since v.5.5.8
*/
so_5::priority_t m_priority = so_5::prio::default_priority;

/*!
* \brief Optional factory for custom direct mboxes.
*
* It can be an empty std::function object.
*
* \since v.5.7.4
*/
custom_direct_mbox_factory_t m_custom_direct_mbox_factory;
};

} /* namespace so_5 */
Expand Down
11 changes: 11 additions & 0 deletions dev/so_5/ret_code.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,17 @@ const int rc_prepared_select_is_active_now = 188;
*/
const int rc_agent_deactivated = 189;

/*!
* \brief An instance of MPSC mbox is expected as custom direct mbox.
*
* Version 5.7.4 allows to set a custom mbox as the direct mbox for
* an agent. That mbox has to be MPSC mbox. An attempt to set MPMC
* mbox as the direct mbox will lead to this error.
*
* \since v.5.7.4
*/
const int rc_mpsc_mbox_expected = 190;

//! \name Common error codes.
//! \{

Expand Down
2 changes: 2 additions & 0 deletions dev/so_5/version.dox
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The standard MPSC mboxes now support delivery filters.
Delivery filters for mutable messages should be set via a new method
so_5::agent_t::so_set_delivery_filter_for_mutable_msg().

A posibility to set a custom mbox as the direct mbox for an agent added.

\section so_5__5_7_3 5.7.3 "Cotopaxi"

Old forms of so_5::abstract_message_chain_t::close(),
Expand Down
1 change: 1 addition & 0 deletions dev/test/so_5/mbox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ add_subdirectory(delivery_filters)
add_subdirectory(local_mbox_growth)
add_subdirectory(custom_mbox_simple)
add_subdirectory(make_new_direct_mbox)
add_subdirectory(custom_direct_mbox_factory)
1 change: 1 addition & 0 deletions dev/test/so_5/mbox/build_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
required_prj( "#{path}/local_mbox_growth/prj.ut.rb" )
required_prj( "#{path}/custom_mbox_simple/prj.ut.rb" )
required_prj( "#{path}/make_new_direct_mbox/prj.ut.rb" )
required_prj( "#{path}/custom_direct_mbox_factory/prj.ut.rb" )
}
2 changes: 2 additions & 0 deletions dev/test/so_5/mbox/custom_direct_mbox_factory/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set(UNITTEST _unit.test.mbox.custom_direct_mbox_factory)
include(${CMAKE_SOURCE_DIR}/cmake/unittest.cmake)
Loading

0 comments on commit facfbfc

Please sign in to comment.