1 /* 2 * An example of use wrapped_env with simple_mtsafe environment 3 * and two working threads with mchains and delayed messages. 4 */ 5 6 #include <so_5/all.hpp> 7 8 // Messages for exchanges between threads. 9 struct tick final : public so_5::signal_t {}; 10 struct tack final : public so_5::signal_t {}; 11 12 // Special signal to stop the exchange. 13 struct stop final : public so_5::signal_t {}; 14 15 // Helper class for removing code duplication in handling the state of one 16 // working thread. 17 class thread_state final 18 { 19 std::chrono::milliseconds pause_{ 750 }; 20 bool must_stop_{ false }; 21 22 public : must_stop() const23 bool must_stop() const { return must_stop_; } 24 25 template<typename Reply> reply_or_stop(const so_5::mchain_t & to)26 void reply_or_stop( const so_5::mchain_t & to ) 27 { 28 if( pause_ > std::chrono::milliseconds(5) ) 29 { 30 pause_ = std::chrono::milliseconds( 31 static_cast< decltype(pause_.count()) >( 32 double(pause_.count()) / 1.5) ); 33 so_5::send_delayed< Reply >( to, pause_ ); 34 } 35 else 36 { 37 so_5::send< stop >( to ); 38 must_stop_ = true; 39 } 40 } 41 }; 42 43 // Body for thread. thread_body(so_5::mchain_t recv_chain,so_5::mchain_t write_chain)44void thread_body( so_5::mchain_t recv_chain, so_5::mchain_t write_chain ) 45 { 46 thread_state state; 47 receive( 48 from(recv_chain).handle_all().stop_on( [&state]{ return state.must_stop(); } ), 49 [&]( so_5::mhood_t<tick> ) { 50 std::cout << "Tick!" << std::endl; 51 state.reply_or_stop< tack >( write_chain ); 52 }, 53 [&]( so_5::mhood_t<tack> ) { 54 std::cout << "Tack!" << std::endl; 55 state.reply_or_stop< tick >( write_chain ); 56 } ); 57 } 58 59 // Just a helper function for preparation of environment params. 60 // It is needed just for shortening of main() function code. make_env_params()61so_5::environment_params_t make_env_params() 62 { 63 so_5::environment_params_t env_params; 64 env_params.infrastructure_factory( 65 so_5::env_infrastructures::simple_mtsafe::factory() ); 66 return env_params; 67 } 68 main()69int main() 70 { 71 so_5::wrapped_env_t sobj( make_env_params() ); 72 73 // An instance for second working thread. 74 // The thread itself will be started later. 75 std::thread second_thread; 76 // This thread must be joined later. 77 const auto thread_joiner = so_5::auto_join( second_thread ); 78 79 // We need two simple mchains for exchange. 80 auto ch1 = create_mchain( sobj ); 81 auto ch2 = create_mchain( sobj ); 82 // The chains must be closed automatically. 83 const auto ch_closer = so_5::auto_close_drop_content( ch1, ch2 ); 84 85 // Launch another thread. 86 second_thread = std::thread( thread_body, ch2, ch1 ); 87 88 // The first message must be initiated. 89 so_5::send< tick >( ch1 ); 90 91 // Launch the interchange on the context of main thread. 92 thread_body( ch1, ch2 ); 93 94 return 0; 95 } 96 97