Should there be agent_t::so_disp_binder() and agent_t::so_coop_default_disp_binder() methods?
eao197 opened this issue · comments
Sometimes it's necessary to bind a child coop to the same dispatcher as the parent coop. Something like:
void parent_agent::evt_some_event(mhood_t<some_msg>) {
// It's time to make a new child coop.
so_5::introduce_child_coop( *this,
// OOPS: I want to specify the same dispatcher as it used for `this` agent, but
// how to get a disp_binder for it?
...);
}
The only solution available today is to pass disp_binder to the constructor of the parent_agent
with storing it inside parent_agent
:
class parent_agent final : public so_5::agent_t
{
so_5::disp_binder_t m_this_binder;
void evt_some_event(mhood_t<some_msg>) {
// It's time to make a new coop.
so_5::introduce_child_coop(*this,
// Now we can specify m_this_binder as the binder for a new coop.
m_this_binder,
...);
}
public:
parent_agent(context_t ctx,
// Disp-binder has to be passed to the constructor.
so_5::disp_binder_t this_binder)
: so_5::agent_t{std::move(ctx)}
, m_this_binder{std::move(this_binder)}
{}
...
};
...
// Somewhere an instance of parent_agent is created.
auto binder = so_5::disp::active_obj::make_dispatcher(env).binder();
env.introduce_coop(binder, [&](so_5::coop_t & coop) {
coop.make_agent<parent_agent>(binder);
...
});
Since v.5.7.5 the disp_binder for an agent is stored inside the agent. So it's possible to add a method like:
[[nodiscard]]
so_5::disp_binder_shptr_t
so_disp_binder() const; /* Open question: should/may it be noexcept? */
to the agent_t
class. This addition will allow to write more simple code:
void parent_agent::evt_some_event(mhood_t<some_msg>) {
// It's time to make a new child coop.
so_5::introduce_child_coop( *this,
// Just use the binder of `this` agent.
so_disp_binder(),
...);
}
Moreover, sometimes parent_agent
may use a different dispatcher. Something like that:
// The thread_pool dispatcher will be used as the default for a coop.
env.introduce_coop(so_5::disp::thread_pool::make_dispatcher(env, 8u).binder(),
[&](so_5::coop_t & coop) {
// But the parent_agent will use one_thread dispatcher.
coop.make_agent_with_binder<parent_agent>(
so_5::disp::one_thread::make_dispatcher(env).binder(),
...);
// Other agents will be bound to the default thread_pool dispatcher.
coop.make_agent<worker>(...);
coop.make_agent<worker>(...);
coop.make_agent<worker>(...);
})
If the parent_agent wants to bind a child coop to the same dispatcher as the parent's coop, then it seems to be possible to provide a so_coop_default_disp_binder()
method to the agent_t
class:
[[nodiscard]]
so_5::disp_binder_shptr_t
so_coop_default_disp_binder() const; /* NOTE: it's not noexcept and may throw! */
This method will allow to write something like that:
void parent_agent::evt_some_event(mhood_t<some_msg>) {
// It's time to make a new child coop.
so_5::introduce_child_coop( *this,
// Just use the binder of the coop of `this` agent.
so_coop_default_disp_binder(),
...);
}
PS. It would be great if someone can provide a feedback related to such a feature. It's it really needed and would be useful for someone?
Implemented in v.5.8.1.