|
SObjectizer (). SObjectizer . , ... - SObjectizer machine_control. , SObjectizer-. SObjectizer- , . , .
Photo by Mike Boening
, - , . , , . , . . , , . , . . , 70 . , 50 . , , 95 , , 50 .
, , . , , . machine_control .
, , , . , . - , - . , , , , .
, . . - , - SObjectizer-. . , ;)
-, . - .
- . , total_status_dashboard, - . :
statuses_analyser. , , - . , statuses_analyser . machine_controller. -.
, , . .
, .. . - , - . , .
, . - . a_machine_t, :
, , , , . . , .
, a_machine_t, , a_machine_t:
// .
enum class engine_state_t { on, off };
// .
enum class cooler_state_t { on, off };
// - .
struct turn_engine_on : public so_5::signal_t {};
struct turn_engine_off : public so_5::signal_t {};
// - .
struct turn_cooler_on : public so_5::signal_t {};
struct turn_cooler_off : public so_5::signal_t {};
// .
struct machine_status
{
// - .
// , .
const std::string m_id;
// .
const engine_state_t m_engine_status;
// .
const cooler_state_t m_cooler_status;
// .
const float m_engine_temperature;
};
, a_machine_t - turn_engine_on/turn_engine_off turn_cooler_on/turn_cooler_off, machine_status.
a_machine_t. :
class a_machine_t : public so_5::agent_t
{
//
// .
struct update_status : public so_5::signal_t {};
// - :
// , ,
const state_t st_engine_on{ this, "on" };
// , .
const state_t st_engine_off{ this, "off" };
// - .
const std::string m_id;
// machine_status.
const so_5::mbox_t m_status_distrib_mbox;
// :
// ,
const float m_initial_temperature;
// ,
const float m_engine_heating_step;
// .
const float m_cooler_impact_step;
// .
float m_engine_temperature;
// .
engine_state_t m_engine_status = engine_state_t::off;
cooler_state_t m_cooler_status = cooler_state_t::off;
// ID update_status.
// SO-5 ID
// ,
// .
so_5::timer_id_t m_update_status_timer;
a_machine_t : . -. , SObjectizer st_engine_on st_engine_off.
update_status. , , m_engine_temperature , . m_status_distrib_mbox machine_status .
. -, so_define_agent(), , SObjectizer. a_machine_t . :
virtual void so_define_agent() override
{
this >>= st_engine_off;
st_engine_on
.event< turn_engine_off >( &a_machine_t::evt_turn_engine_off )
.event< turn_cooler_on >( &a_machine_t::evt_turn_cooler_on )
.event< turn_cooler_off >( &a_machine_t::evt_turn_cooler_off )
.event< update_status >( &a_machine_t::evt_update_status_when_engine_on );
st_engine_off
.event< turn_engine_on >( &a_machine_t::evt_turn_engine_on )
.event< turn_cooler_on >( &a_machine_t::evt_turn_cooler_on )
.event< turn_cooler_off >( &a_machine_t::evt_turn_cooler_off )
.event< update_status >( &a_machine_t::evt_update_status_when_engine_off );
}
, update_status . , st_engine_on turn_engine_on , . turn_engine_off st_engine_off.
so_define_agent() : , . .
, . . , so_define_agent() , . (, so_define_agent() , ).
, , so_define_agent() , : , so_define_agent() . .
so_evt_start(). SObjectizer , SObjectizer-. a_machine_t so_evt_start() , update_status:
virtual void so_evt_start() override
{
// update_status
// ID , ,
// .
m_update_status_timer = so_5::send_periodic< update_status >(
// .
*this,
// .
std::chrono::milliseconds(0),
// 200ms.
std::chrono::milliseconds(200) );
}
a_machine_t. , SObjectizer -. - . , :
st_engine_on
.event< turn_engine_off >( &a_machine_t::evt_turn_engine_off )
SObjectizer-, turn_engine_off, evt_turn_engine_off().
a_machine_t , :
void evt_turn_engine_off()
{
// .
this >>= st_engine_off;
// .
m_engine_status = engine_state_t::off;
}
void evt_turn_engine_on()
{
this >>= st_engine_on;
m_engine_status = engine_state_t::on;
}
void evt_turn_cooler_off()
{
// .
// .
m_cooler_status = cooler_state_t::off;
}
void evt_turn_cooler_on()
{
m_cooler_status = cooler_state_t::on;
}
update_status . update_status :
void evt_update_status_when_engine_on()
{
m_engine_temperature += m_engine_heating_step;
if( cooler_state_t::on == m_cooler_status )
m_engine_temperature -= m_cooler_impact_step;
distribute_status();
}
, , . , , .
update_status st_engine_off, .. , , :
void evt_update_status_when_engine_off()
{
if( cooler_state_t::on == m_cooler_status )
{
m_engine_temperature -= m_cooler_impact_step;
//
// .
if( m_engine_temperature < m_initial_temperature )
m_engine_temperature = m_initial_temperature;
}
distribute_status();
}
distribute_status() , .. machine_status :
void distribute_status()
{
// send- machine_status,
// send.
//
// m_status_distrib_mbox.
so_5::send< machine_status >(
// .
m_status_distrib_mbox,
//
// machine_status.
m_id,
m_engine_status,
m_cooler_status,
m_engine_temperature );
}
, - : a_machine_t / ? , , a_machine_t - ?
, :)
- - , , . (): , .
a_machine_t : ( ). a_machine_t / , - - -, , - . .
a_machine_t , , - , , . a_machine_t .
a_total_status_dashboard_t machine_status, .
a_total_status_dashboard_t :
virtual void so_define_agent() override
{
so_subscribe( m_status_distrib_mbox )
.event( &a_total_status_dashboard_t::evt_machine_status );
so_subscribe_self().event< show_dashboard >(
&a_total_status_dashboard_t::evt_show_dashboard );
}
, machine_status, , a_machine_t machine_status-. , show_dashboard, a_total_status_dashboard_t :
virtual void so_evt_start() override
{
//
// .
const auto period = std::chrono::milliseconds( 1500 );
m_show_timer = so_5::send_periodic< show_dashboard >( *this,
period, period );
}
a_total_status_dashboard_t , a_machine_t so_evt_start(), SObjectizer a_total_status_dashboard_t.
machine_status : :
void evt_machine_status( const machine_status & status )
{
m_machine_statuses[ status.m_id ] = one_machine_status_t{
status.m_engine_status, status.m_cooler_status,
status.m_engine_temperature
};
}
show_dashboard : :
void evt_show_dashboard()
{
auto old_precision = std::cout.precision( 5 );
std::cout << "=== The current status ===" << std::endl;
for( const auto & m : m_machine_statuses )
{
show_one_status( m );
}
std::cout << "==========================" << std::endl;
std::cout.precision( old_precision );
}
a_total_status_dashboard_t , . , a_total_status_dashboard_t .
machine_control a_machine_t - .
-, a_statuses_analyser_t, machine_status, , a_machine_t - .
-, - a_machine_controller_t, a_statuses_analyser_t . , a_machine_controlle_t , turn_cooler_on a_machine_t. a_machine_controller_t , turn_engine_off. ..
, a_statuses_analyser_t a_machine_controller_t . a_statuses_analyser_t, , . , , a_statuses_analyser_t .
machaine_control SObjectizer-, , - , a_statuses_analyser_t a_machine_controller_t.
, a_machine_t, a_statuses_analyser_t a_machine_controller_t :
machine_needs_attention :
// , .
enum class attention_t
{
none,
engine_cooling_done,
engine_cooling_needed,
engine_overheat_detected
};
// , - .
struct machine_needs_attention
{
// - .
const std::string m_id;
// .
const attention_t m_attention;
// (/).
const engine_state_t m_engine_status;
// (/).
const cooler_state_t m_cooler_status;
};
a_statuses_analyser_t , machine_status. , , , a_statuses_analyser_t machine_needs_attention. a_machine_controller_t a_machine_t .
a_statuses_analyser_t . , -. ( - , ), :
, .
a_statuses_analyser_t, SObjectizer-, : - so_define_agent() - :
virtual void so_define_agent() override
{
so_subscribe( m_status_distrib_mbox ).event(
&a_statuses_analyzer_t::evt_machine_status );
}
void evt_machine_status( const machine_status & status )
{
auto it = m_last_infos.find( status.m_id );
if( it == m_last_infos.end() )
// .
// .
it = m_last_infos.insert( last_info_map_t::value_type {
status.m_id,
last_machine_info_t {
attention_t::none,
status.m_engine_temperature
} } ).first;
handle_new_status( status, it->second );
}
handle_new_status(), evt_machine_status(), -, .
a_machine_controller_t : a_statuses_analyser_t , , , . -, . -, , .
a_statuses_analyser_t, . a_statuses_analyser_t -. a_machine_controller_t. a_machine_controller_t , . , a_machine_contoller_t machine_needs_attention -. , a_machine_controller_t machine_needs_attention .
- a_machine_controller_t , :
template< class LOGIC >
class a_machine_controller_t : public so_5::agent_t
{
public :
a_machine_controller_t(
context_t ctx,
so_5::priority_t priority,
so_5::mbox_t status_distrib_mbox,
const machine_dictionary_t & machines )
: so_5::agent_t( ctx + priority )
, m_status_distrib_mbox( std::move( status_distrib_mbox ) )
, m_machines( machines )
, m_logic()
{}
virtual void so_define_agent() override
{
so_set_delivery_filter( m_status_distrib_mbox,
[this]( const machine_needs_attention & msg ) {
return m_logic.filter( msg );
} );
so_subscribe( m_status_distrib_mbox )
.event( [this]( const machine_needs_attention & evt ) {
m_logic.action( m_machines, evt );
} );
}
private :
const so_5::mbox_t m_status_distrib_mbox;
const machine_dictionary_t & m_machines;
const LOGIC m_logic;
};
, , : , a_machine_controller_t. LOGIC :
struct LOGIC
{
bool filter( const machine_needs_attention & msg ) const;
void action(
const machine_dictionary_t & machines,
const machine_needs_attention & evt ) const;
};
C++11 , , , a_machine_controller_t, . , .. C++11 , .
a_machine_controller_t LOGIC . , , -.
:
-, , . a_machine_controller_t :
so_set_delivery_filter( m_status_distrib_mbox,
[this]( const machine_needs_attention & msg ) {
return m_logic.filter( msg );
} );
SObjectizer-. , T M, T, , .
so_set_delivery_filter() , -, M , T. true, . false, , , .
. Subscriber-1 mbox-. Subscriber-2 , .
LOGIC::filter() , machine_needs_attention, .
-, - machine_needs_attention, , .
LOGIC::action(). a_machine_controller_t machine_needs_attention:
so_subscribe( m_status_distrib_mbox )
.event( [this]( const machine_needs_attention & evt ) {
m_logic.action( m_machines, evt );
} );
, , a_machine_controller_t, . , turn_engine_off, :
struct engine_stopper_t
{
bool filter( const machine_needs_attention & msg ) const
{
return msg.m_attention == attention_t::engine_overheat_detected;
}
void action(
const machine_dictionary_t & machines,
const machine_needs_attention & evt ) const
{
so_5::send< turn_engine_off >( machines.find_mbox( evt.m_id ) );
}
};
.. machine_needs_attention, . , - turn_engine_off.
:
struct cooler_starter_t
{
bool filter( const machine_needs_attention & msg ) const
{
return (msg.m_attention == attention_t::engine_overheat_detected ||
msg.m_attention == attention_t::engine_cooling_needed) &&
msg.m_cooler_status == cooler_state_t::off;
}
void action(
const machine_dictionary_t & machines,
const machine_needs_attention & evt ) const
{
so_5::send< turn_cooler_on >( machines.find_mbox( evt.m_id ) );
}
};
. , , .
:
, a_machine_controller_t .
machine_control , machine_needs_attention . , machine_needs_attention attention_t::engine_overheat_detected cooler_status_t::off, : engine_stopper_t, cooler_starter_t.
, . , engine_overheat_detected turn_engine_off, turn_cooler_on. - , . , . , .
SObjectizer- ?
. , . , . . , , .
SObjectizer : , . so_5::disp::prio_one_thread::strictly_ordered. a_machine_controller_t .
- :
, a_machine_controller_t :
a_machine_controller_t(
...,
so_5::priority_t priority,
... )
: so_5::agent_t( ctx + priority )
, ...
{}
:
coop.make_agent_with_binder< a_machine_controller_t< engine_stopper_t > >(
disp->binder(),
so_5::prio::p4,
status_distrib_mbox,
machines );
coop.make_agent_with_binder< a_machine_controller_t< cooler_starter_t > >(
disp->binder(),
so_5::prio::p3,
status_distrib_mbox,
machines );
so_5::prio::p4 so_5::prio::p3 .
, a_machine_t st_engine_off, .. . , . , a_machine_t, a_machine_controller_t ?
, - -, turn_engine_on -.
, C++ , a_machine_t, a_total_status_dashboard_t, a_statuses_analyser_t a_machine_controller_t. , ad-hoc . .. , -. machine_control :
coop.define_agent().on_start( [&dict] {
dict.for_each(
[]( const std::string &, const so_5::mbox_t & mbox ) {
so_5::send< turn_engine_on >( mbox );
} );
} );
define_agent() ad-hoc , . ad-hoc SObjectizer-: turn_engine_on.
SObjectizer-, , .
. - . SObjectizer . , .
machine_control , :
, , , : machine_dictionary. , - - .
, - ( machine_status machine_needs_attention) . SObjectizer , , , turn_engine_on, . machine_dictionary.
, , , .
, , , , a_machine_t a_machine_controller_t, .
SObjectizer-, ad-hoc . , , - SObjectizer, , , , . -, , ping-pong, , . , SObjectizer.
, , . , , Actor Model Publish/Subscribe .
machine_control , (.. ) .
, a_machine_t machine_status , , . a_machine_t ( ) . , .
a_machine_t ( turn_engine_on), , . a_machine_t , . , a_machine_t .
, - turn_engine_on a_machine_t, Actor Model, 1:1.
machine_status machine_needs_attention Actor Model, .. 1:N. Publish/Subscribe. , machine_status machine_needs_attention, . - Publish. Subscribe, , , a_total_status_dashboard_t, a_statuses_analyser_t a_machine_controller_t so_define_agent().
, SObjectizer: . , SObjectizer multi-producer/multi-consumer , 1:N.
, machine_status, , , . a_total_status_dashboard_t machine_status . a_statuses_analyser_t machine_status a_machine_t.
. , . a_total_status_dashboard_t a_statuses_analyser_t. a_total_status_dashboard_t - a_gui_status_dashboard_t, std::cout, . , , , machine_status.
SObjectizer , , . SObjectizer , ( CSP- ).
SObjectizer , , . (.. ), .
, . . , . -, - , so_5::signal_t, . , - , - . , , - - .
, , .
, SObjectizer- so_5_extra, SObjectizer. , SObjectizer , , . so_5_extra , . - SObjectizer, . SObjectizer, so_5_extra.