Skip to content

Should there be agent_t::so_disp_binder() and agent_t::so_coop_default_disp_binder() methods? #71

@eao197

Description

@eao197

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?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions