SObjectizer 5.8
Loading...
Searching...
No Matches
so_5/named_dispatchers_layer/main.cpp
/*
* An example of usage of SObjectizer's layer for holding a dictionary of named
* dispatchers.
*/
#include <iostream>
#include <so_5/all.hpp>
// Implemetation of SObjectizer's layer that plays a role of
// a dictionary of named one_thread dispatchers.
class disp_binder_dictionary_layer_t : public so_5::layer_t
{
// Type of dictionary for holding dispatcher binders.
using map_t = std::map<std::string, so_5::disp_binder_shptr_t, std::less<>>;
// Because layer can be used from different worker threads it should
// be protected.
std::mutex m_lock;
// The dictionary.
map_t m_dict;
public:
// There is no need to override start()/shutdown()/wait() methods
// because the basic implementation does nothing.
// An interface of dictionary.
// Add a new binder if there is no such name in the dictionary.
void add(
const std::string & name,
{
std::lock_guard<std::mutex> l{m_lock};
auto [it, inserted] = m_dict.emplace(name, std::move(binder));
(void)it; // To suppress warnings about unused variables.
if(!inserted)
throw std::runtime_error(name + ": is not unique name");
}
// Try find binder in the dictionary.
// Absence of a binder is not an error.
std::optional<so_5::disp_binder_shptr_t>
try_get(std::string_view name) noexcept
{
std::lock_guard<std::mutex> l{m_lock};
if(const auto it = m_dict.find(name); it != m_dict.end())
return { it->second };
else
return std::nullopt;
}
// Try get binder from the dictinary.
// Absence of a binder is reported by an exception.
get(std::string_view name)
{
auto r = try_get(name);
if(!r) throw std::runtime_error("binder is not found");
return std::move(*r);
}
};
// Type of demo agent to be used in the example.
//
// This agent tells the parent about its start and then deregisters itself.
//
class a_child_t final : public so_5::agent_t
{
public:
// Type of signal to be sent to the parent.
struct i_am_completed final : public so_5::signal_t {};
a_child_t(context_t ctx, so_5::mbox_t parent)
: so_5::agent_t{std::move(ctx)}
, m_parent{std::move(parent)}
{}
void so_evt_start() override
{
}
private:
const so_5::mbox_t m_parent;
};
// Another type of demo agent to be used in the example.
class a_parent_t final : public so_5::agent_t
{
public:
a_parent_t(context_t ctx, std::string disp_name)
: so_5::agent_t{std::move(ctx)}
, m_disp_name{std::move(disp_name)}
{}
void so_define_agent() override
{
[this](mhood_t<a_child_t::i_am_completed>) {
// We can finish our work too.
std::cout << "child from '" << m_disp_name << "' completed"
<< std::endl;
});
}
void so_evt_start() override
{
// Create a new child on the specified dispatcher.
[this](so_5::coop_t & coop) {
auto binder = so_environment().query_layer<
disp_binder_dictionary_layer_t
>()->get(m_disp_name);
coop.make_agent_with_binder<a_child_t>(binder, so_direct_mbox());
});
}
private:
const std::string m_disp_name;
};
int main()
{
[](so_5::environment_t & env) {
// Create several dispatchers and give them names.
auto * layer = env.query_layer<disp_binder_dictionary_layer_t>();
layer->add("first",
layer->add("second",
layer->add("third",
// Create several parent agents. All of them will work on
// the default dispatcher.
env.register_agent_as_coop(env.make_agent<a_parent_t>("first"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("second"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("third"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("second"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("first"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("third"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("third"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("third"));
env.register_agent_as_coop(env.make_agent<a_parent_t>("third"));
// Wait while all parents finish their work.
},
// Our layer should be created and stored in params.
params.add_layer(std::make_unique<disp_binder_dictionary_layer_t>());
});
return 0;
}
A helper header file for including all public SObjectizer stuff.
A base class for agents.
Definition agent.hpp:673
virtual void so_define_agent()
Hook on define agent for SObjectizer.
Definition agent.cpp:841
subscription_bind_t so_subscribe_self()
Initiate subscription to agent's direct mbox.
Definition agent.hpp:1416
void so_deregister_agent_coop_normally()
A helper method for deregistering agent's coop in case of normal deregistration.
Definition agent.cpp:982
const mbox_t & so_direct_mbox() const
Get the agent's direct mbox.
Definition agent.cpp:762
environment_t & so_environment() const noexcept
Access to the SObjectizer Environment which this agent is belong.
Definition agent.cpp:853
virtual void so_evt_start()
Hook on agent start inside SObjectizer.
Definition agent.cpp:701
Agent cooperation.
Definition coop.hpp:389
Agent * make_agent_with_binder(so_5::disp_binder_shptr_t binder, Args &&... args)
Helper method for simplification of agents creation and binding to the specified dispatcher.
Definition coop.hpp:827
Parameters for the SObjectizer Environment initialization.
SObjectizer Environment.
coop_handle_t register_agent_as_coop(std::unique_ptr< A > agent)
Register single agent as a cooperation.
std::unique_ptr< Agent > make_agent(Args &&... args)
Helper method for simplification of agents creation.
SO_Layer * query_layer() const
Get access to the layer with exception if layer is not found.
An interface of the additional SObjectizer Environment layer.
Definition so_layer.hpp:31
A base class for agent signals.
Definition message.hpp:275
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, subscription_bind_t & >::type event(Method_Pointer pfn, thread_safety_t thread_safety=not_thread_safe)
Make subscription to the message.
Definition agent.hpp:3490
SO_5_FUNC dispatcher_handle_t make_dispatcher(environment_t &env, const std::string_view data_sources_name_base, disp_params_t params)
Create an instance of one_thread dispatcher.
Private part of message limit implementation.
Definition agent.cpp:33
void launch(Init_Routine &&init_routine)
Launch a SObjectizer Environment with default parameters.
Definition api.hpp:142
decltype(auto) introduce_child_coop(agent_t &owner, Args &&... args)
A simple way for creating and registering child cooperation.
void send(Target &&to, Args &&... args)
A utility function for creating and delivering a message or a signal.
std::shared_ptr< disp_binder_t > disp_binder_shptr_t
Typedef for the disp_binder smart pointer.