Skip to content

Commit

Permalink
Refactoring and resolution of documentation-related FIXME.
Browse files Browse the repository at this point in the history
  • Loading branch information
eao197 committed Mar 18, 2024
1 parent fd224ab commit b2441ee
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 14 deletions.
2 changes: 1 addition & 1 deletion dev/so_5/agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ agent_t::so_agent_name() const noexcept
if( m_name.has_value() )
return { m_name.as_string_view() };
else
return { static_cast<const void *>(this) };
return { this };
}

void
Expand Down
45 changes: 42 additions & 3 deletions dev/so_5/agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ struct working_thread_id_sentinel_t
class SO_5_TYPE agent_t
: private atomic_refcounted_t
, public message_limit::message_limit_methods_mixin_t
, public name_for_agent_methods_mixin_t
{
friend class subscription_bind_t;
friend class state_t;
Expand Down Expand Up @@ -2709,7 +2710,41 @@ class SO_5_TYPE agent_t
disp_binder_shptr_t
so_this_coop_disp_binder() const;

//FIXME: document this!
/*!
* \brief Get an optional name of the agent.
*
* If agent has the name then a reference to this name will be returned.
* Otherwise a small object with a pointer to agent will be returned.
*
* The result can be printed to std::ostream or converted into a string:
* \code
* class my_agent final : public so_5::agent_t
* {
* ...
* void so_evt_start() override
* {
* std::cout << so_agent_name() << ": started" << std::endl;
* ...
* so_5::send<std::string>(some_mbox, so_agent_name().to_string());
* }
* void so_evt_finished() override
* {
* std::cout << so_agent_name() << ": stopped" << std::endl;
* }
* ...
* }
* \endcode
*
* \attention
* This method returns a lightweight object that just holds a reference
* to the agent's name (or a pointer to the agent). This object should
* not be stored for the long time, because the references/pointers it
* holds may become invalid. If you have to store the agent name for
* a long time please convert the returned value into std::string and
* store the resulting std::string object.
*
* \since v.5.8.2
*/
[[nodiscard]]
agent_identity_t
so_agent_name() const noexcept;
Expand Down Expand Up @@ -2879,13 +2914,17 @@ class SO_5_TYPE agent_t
*/
disp_binder_shptr_t m_disp_binder;

//FIXME: document this!
/*!
* \brief Optional name for the agent.
*
* This value can be set in the constructor only and can't be changed
* later.
*
* Empty value means that the name for the agent wasn't specified.
*
* \since v.5.8.2
*/
name_for_agent_t m_name;
const name_for_agent_t m_name;

//! Destroy all agent's subscriptions.
/*!
Expand Down
38 changes: 33 additions & 5 deletions dev/so_5/agent_identity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,29 @@
namespace so_5
{

//FIXME: document this!
/*!
* \brief Helper class for holding agent's identity (name or pointer).
*
* Since v.5.8.2 agents may have an optional name. If a name is set for agent
* a reference to this name can be returned by agent_t::so_agent_name(). But
* if a name is not specified then only a pointer to agent (agent_t's `this` value)
* can be used as agent's identity.
*
* This type is intended to be used as a thin wrapper that covers cases described
* above. It holds a reference to agent's name if the name is specified or
* just pointer to an agent if there is no name. This type can be seen as
* a more as more convenient version of:
* \code
* std::variant<std::string_view, const agent_t*>;
* \endcode
*
* \attention
* Objects of this type hold references, not values. So it's not safe to store
* them for a long time. Please consider to store `std::string` objects
* returned by to_string() methods instead of agent_identity_t objects.
*
* \since v.5.8.2
*/
class agent_identity_t
{
friend class agent_t;
Expand All @@ -39,7 +61,7 @@ class agent_identity_t
+ 1u /* terminating 0-symbol */;

//! Value.
const void * m_pointer_value;
const agent_t * m_pointer_value;

// NOTE: this method is implemented in agent.cpp source file.
//! Make a c-string with text representation of a value.
Expand All @@ -55,7 +77,10 @@ class agent_identity_t
std::string_view m_name;
};

//FIXME: document this!
/*!
* Helper type to be used with std::visit when agent_identity has to
* be converted into a string.
*/
struct to_string_visitor_t
{
[[nodiscard]]
Expand All @@ -74,7 +99,10 @@ class agent_identity_t
}
};

//FIXME: document this!
/*!
* Helper type to be used with std::visit when agent_identity has to
* be printed into a std::ostream.
*/
struct to_ostream_visitor_t
{
std::ostream & m_to;
Expand Down Expand Up @@ -102,7 +130,7 @@ class agent_identity_t
value_t m_value;

//! Initializing constructor for case when agent has no user specified name.
agent_identity_t( const void * pointer ) noexcept
agent_identity_t( const agent_t * pointer ) noexcept
: m_value{ pointer_only_t{ pointer } }
{}

Expand Down
57 changes: 53 additions & 4 deletions dev/so_5/agent_tuning_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,24 @@ using custom_direct_mbox_factory_t = std::function<

// NOTE: the implementation of name_for_agent_t is in agent.cpp

//FIXME: document this!
/*!
* \brief Type for holding agent name.
*
* Unlike std::string it has no small-string optimization, but its size is just
* a (sizeof(char *)+sizeof(unsigned int)), so it is smaller than std::string in
* cases when agent's name is empty.
*
* \note
* This type holds a copy of name (without the terminal 0-symbol). If name is
* not set (or if the content of the object is moved out) then a nullptr is
* held and the object is treated as empty or null-object.
*
* \attention
* The size of a name has to be fit into `unsigned int`, not into `std::size_t`,
* so name of agent can't exceed 4GiB if `unsigned int` is 32-bit.
*
* \since v.5.8.2
*/
class SO_5_TYPE name_for_agent_t
{
static_assert( sizeof(unsigned int) <= sizeof(std::size_t),
Expand Down Expand Up @@ -124,9 +141,41 @@ class SO_5_TYPE name_for_agent_t

//! Does this object have a value?
explicit operator bool() const noexcept
{
return this->has_value();
}
{
return this->has_value();
}
};

/*!
* \brief Helper type with method to be mixed into agent class.
*
* \since v.5.8.2
*/
struct name_for_agent_methods_mixin_t
{
/*!
* \brief A helper factory for making #name_for_agent_t instance.
*
* Usage example:
* \code
* class my_agent final : public so_5::agent_t
* {
* public:
* my_agent(context_t ctx, std::string_view name)
* : so_5::agent_t{ ctx + name_for_agent(name) }
* {}
* ...
* }
* \endcode
*
* \since v.5.8.2
*/
[[nodiscard]]
static name_for_agent_t
name_for_agent( std::string_view name )
{
return name_for_agent_t{ name };
}
};

#if defined( SO_5_MSVC )
Expand Down
2 changes: 1 addition & 1 deletion dev/test/so_5/agent/agent_name/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class named_agent_t final : public so_5::agent_t
{
public:
named_agent_t( context_t ctx )
: so_5::agent_t{ ctx + so_5::name_for_agent_t{ "Alice" } }
: so_5::agent_t{ ctx + name_for_agent( "Alice" ) }
{}

void
Expand Down

0 comments on commit b2441ee

Please sign in to comment.