1 /* 2 * A sample of the simpliest agent which has several states. 3 * The agent uses different handlers for the same message. 4 * At the beginning of its work agent initiates a periodic message. 5 * Then agent handles this messages and switches from one state 6 * to another. 7 * 8 * A work of the SObjectizer Environment is finished after the agent 9 * switched to the final state. 10 * 11 * State switching is fixed by a state listener. 12 */ 13 14 #if defined( _MSC_VER ) 15 #if defined( __clang__ ) 16 #pragma clang diagnostic ignored "-Wreserved-id-macro" 17 #endif 18 #define _CRT_SECURE_NO_WARNINGS 19 #endif 20 21 #include <iostream> 22 #include <time.h> 23 24 // Main SObjectizer header file. 25 #include <so_5/all.hpp> 26 27 // Periodic message. 28 class msg_periodic final : public so_5::signal_t {}; 29 30 // State listener for fixing state changes. 31 class state_monitor_t final : public so_5::agent_state_listener_t 32 { 33 const std::string m_type_hint; 34 35 public: state_monitor_t(const std::string & type_hint)36 state_monitor_t( const std::string & type_hint ) 37 : m_type_hint( type_hint ) 38 {} 39 changed(so_5::agent_t &,const so_5::state_t & state)40 void changed( 41 so_5::agent_t &, 42 const so_5::state_t & state ) noexcept override 43 { 44 std::cout << m_type_hint << " agent changed state to " 45 << state.query_name() 46 << std::endl; 47 } 48 }; 49 50 // A sample agent class. 51 class a_state_swither_t final : public so_5::agent_t 52 { 53 // Agent states. 54 const state_t st_1{ this, "state_1" }; 55 const state_t st_2{ this, "state_2" }; 56 const state_t st_3{ this, "state_3" }; 57 const state_t st_shutdown{ this, "shutdown" }; 58 59 public: a_state_swither_t(context_t ctx)60 a_state_swither_t( context_t ctx ) 61 : so_5::agent_t{ ctx } 62 {} 63 64 // Definition of the agent for SObjectizer. 65 void so_define_agent() override; 66 67 // Reaction to start into SObjectizer. 68 void so_evt_start() override; 69 70 // Message handler for the default state. 71 void evt_handler_default( mhood_t<msg_periodic> ); 72 73 // Message handler for the state_1. 74 void evt_handler_1( mhood_t<msg_periodic> ); 75 76 // Message handler for the state_2. 77 void evt_handler_2( mhood_t<msg_periodic> ); 78 79 // Message handler for the state_3. 80 void evt_handler_3( mhood_t<msg_periodic> ); 81 82 // Message handler for the shutdown_state. 83 void evt_handler_shutdown( mhood_t<msg_periodic> ); 84 85 private: 86 // Timer event id. 87 // If we do not store it the periodic message will 88 // be canceled automatically. 89 so_5::timer_id_t m_timer_id; 90 91 // Helper method for showing that event handler is called. 92 void show_event_invocation( const char * event_name ); 93 }; 94 so_define_agent()95void a_state_swither_t::so_define_agent() 96 { 97 // Message subsription. 98 so_subscribe_self() 99 .event( &a_state_swither_t::evt_handler_default ); 100 101 so_subscribe_self().in( st_1 ) 102 .event( &a_state_swither_t::evt_handler_1 ); 103 104 so_subscribe_self().in( st_2 ) 105 .event( &a_state_swither_t::evt_handler_2 ); 106 107 so_subscribe_self().in( st_3 ) 108 .event( &a_state_swither_t::evt_handler_3 ); 109 110 so_subscribe_self().in( st_shutdown ) 111 .event( &a_state_swither_t::evt_handler_shutdown ); 112 } 113 so_evt_start()114void a_state_swither_t::so_evt_start() 115 { 116 show_event_invocation( "so_evt_start()" ); 117 118 // Periodic message should be initiated. 119 m_timer_id = so_5::send_periodic< msg_periodic >( 120 *this, 121 std::chrono::seconds( 1 ), 122 std::chrono::seconds( 1 ) ); 123 } 124 evt_handler_default(mhood_t<msg_periodic>)125void a_state_swither_t::evt_handler_default( mhood_t<msg_periodic> ) 126 { 127 show_event_invocation( "evt_handler_default" ); 128 129 // Switching to the next state. 130 so_change_state( st_1 ); 131 } 132 evt_handler_1(mhood_t<msg_periodic>)133void a_state_swither_t::evt_handler_1( mhood_t<msg_periodic> ) 134 { 135 show_event_invocation( "evt_handler_1" ); 136 137 // Switching to the next state. 138 so_change_state( st_2 ); 139 } 140 evt_handler_2(mhood_t<msg_periodic>)141void a_state_swither_t::evt_handler_2( mhood_t<msg_periodic> ) 142 { 143 show_event_invocation( "evt_handler_2" ); 144 145 // Switching to the next state. 146 so_change_state( st_3 ); 147 } 148 evt_handler_3(mhood_t<msg_periodic>)149void a_state_swither_t::evt_handler_3( mhood_t<msg_periodic> ) 150 { 151 show_event_invocation( "evt_handler_3" ); 152 153 // Switching to the next state. 154 so_change_state( st_shutdown ); 155 } 156 evt_handler_shutdown(mhood_t<msg_periodic>)157void a_state_swither_t::evt_handler_shutdown( mhood_t<msg_periodic> ) 158 { 159 show_event_invocation( "evt_handler_3" ); 160 161 // Switching to the default state. 162 so_change_state( so_default_state() ); 163 164 // Finishing SObjectizer's work. 165 std::cout << "Stop sobjectizer..." << std::endl; 166 so_environment().stop(); 167 } 168 show_event_invocation(const char * event_name)169void a_state_swither_t::show_event_invocation( const char * event_name ) 170 { 171 time_t t = time( nullptr ); 172 std::cout << asctime( localtime( &t ) ) 173 << event_name << ", state: " << so_current_state().query_name() 174 << std::endl; 175 } 176 177 // A state listener. 178 state_monitor_t g_state_monitor( "nondestroyable_listener" ); 179 180 // The SObjectizer Environment initialization. init(so_5::environment_t & env)181void init( so_5::environment_t & env ) 182 { 183 auto ag = env.make_agent< a_state_swither_t >(); 184 185 // Adding the state listener. Its lifetime is not controlled by the agent. 186 ag->so_add_nondestroyable_listener( g_state_monitor ); 187 188 // Adding another state listener. 189 // Its lifetime is controlled by the agent. 190 ag->so_add_destroyable_listener( 191 std::make_unique< state_monitor_t >( "destroyable_listener" ) ); 192 193 // Creating and registering a cooperation. 194 env.register_agent_as_coop( std::move(ag) ); 195 } 196 main()197int main() 198 { 199 try 200 { 201 so_5::launch( &init ); 202 } 203 catch( const std::exception & ex ) 204 { 205 std::cerr << "Error: " << ex.what() << std::endl; 206 return 1; 207 } 208 209 return 0; 210 } 211 212