SObjectizer  5.5
so-5.5.4: Another constructor for agent_t with context_t argument

Since v.5.5.3 there is a possibility to tune agent options. For example, if it is required to change subscription storage for an agent it could be written as:

class my_agent_with_many_subscriptions : public so_5::rt::agent_t
{
public :
my_agent_with_many_subscriptions(
some_agent_specific_params params )
: so_5::rt::agent_t(
// Passing env to the parent.
env,
// Passing agent options to the parent.
tuning_options().subscription_storage_factory(
so_5::rt::hash_table_based_subscription_factory() ) )
, ...
{...}
...
};

But what if we want to create a derived class from my_agent_with_many_subscriptions and specify additional agent's options in the constructor of the derived class? How can we do that?

The only way for that in v.5.5.3 was the definition of another constructor for base class. That constructor must receive so_5::rt::agent_tuning_options_t object:

// Our base class.
class my_agent_with_many_subscriptions : public so_5::rt::agent_t
{
public :
// Constructor for the case when there are no additional options.
my_agent_with_many_subscriptions(
some_agent_specific_params params )
: // Delegate work to different constructor.
my_agent_with_many_subscriptions(
env,
// Default tuning options.
tuning_options(),
// Other arguments...
params )
{}
// Constructor for the case when there are some additional options.
my_agent_with_many_subscriptions(
some_agent_specific_params params )
: so_5::rt::agent_t(
// Passing env to the parent.
env,
// Passing agent options to the parent.
options.subscription_storage_factory(
so_5::rt::hash_table_based_subscription_factory() ) )
, ...
{...}
...
};
// Our derived class.
class my_agent_with_limits : public my_agent_with_many_subscriptions
{
public :
my_agent_with_limits(
some_agent_specific_params params )
: my_agent_with_many_subscriptions(
env,
// Our part of agent options.
tuning_options().message_limits(
limit_then_drop< request_one >( 100 ),
limit_then_drop< request_two >( 100 ),
... ),
params )
{...}
...
};

But this approach requires definition of yet another constructor for an agent. And yet another constructor of agent of derived class and so on. And the definition of another constructor in base class is not always possible if that class is coming from 3rd-party library and we don't want to patch the library source code.

Version 5.5.4 provides the solution for that problem.

Since v.5.5.4 it is possible to define agent's constructors which accept argument of the type so_5::rt::agent_t::context_t (which is an alias for so_5::rt::agent_context_t). This type can be seen as a pair of reference to SObjectizer Environment object and so_5::rt::agent_tuning_option_t object. The context_t instance can be used instead of environment_t reference. It allows to write like this:

// Our base class.
class my_agent_with_many_subscriptions : public so_5::rt::agent_t
{
public :
// Constructor for both cases: either there are additional options or not.
my_agent_with_many_subscriptions(
context_t ctx,
some_agent_specific_params params )
: // We can simply pass new context to the base class.
so_5::rt::agent_t(
// Tune our agent by adding appropriate factory.
ctx + so_5::rt::hash_table_based_subscription_factory() )
, ...
{...}
...
};
// Our derived class.
class my_agent_with_limits : public my_agent_with_many_subscriptions
{
public :
my_agent_with_limits(
context_t ctx,
some_agent_specific_params params )
: my_agent_with_many_subscriptions(
// Our part of agent options.
ctx + limit_then_drop< request_one >( 100 )
+ limit_then_drop< request_two >( 100 )
+ ...,
params )
{...}
...
};

Please note two important features of context_t:

Because of that the usage of context_t instead environment_t is recommended since v.5.5.4.