class atm { messaging::receiver incoming; messaging::sender bank; messaging::sender interface_hardware; void (atm::*state)(); std::string account; unsigned withdrawal_amount; std::string pin; void process_withdrawal() { incoming.wait() .handle( [&](withdraw_ok const& msg) { interface_hardware.send( issue_money(withdrawal_amount)); bank.send( withdrawal_processed(account,withdrawal_amount)); state=&atm::done_processing; } ) .handle( [&](withdraw_denied const& msg) { interface_hardware.send(display_insufficient_funds()); state=&atm::done_processing; } ) .handle( [&](cancel_pressed const& msg) { bank.send( cancel_withdrawal(account,withdrawal_amount)); interface_hardware.send( display_withdrawal_cancelled()); state=&atm::done_processing; } ); } void process_balance() { incoming.wait() .handle( [&](balance const& msg) { interface_hardware.send(display_balance(msg.amount)); state=&atm::wait_for_action; } ) .handle( [&](cancel_pressed const& msg) { state=&atm::done_processing; } ); } void wait_for_action() { interface_hardware.send(display_withdrawal_options()); incoming.wait() .handle( [&](withdraw_pressed const& msg) { withdrawal_amount=msg.amount; bank.send(withdraw(account,msg.amount,incoming)); state=&atm::process_withdrawal; } ) .handle( [&](balance_pressed const& msg) { bank.send(get_balance(account,incoming)); state=&atm::process_balance; } ) .handle( [&](cancel_pressed const& msg) { state=&atm::done_processing; } ); } void verifying_pin() { incoming.wait() .handle( [&](pin_verified const& msg) { state=&atm::wait_for_action; } ) .handle( [&](pin_incorrect const& msg) { interface_hardware.send( display_pin_incorrect_message()); state=&atm::done_processing; } ) .handle( [&](cancel_pressed const& msg) { state=&atm::done_processing; } ); } void getting_pin() { incoming.wait() .handle( [&](digit_pressed const& msg) { unsigned const pin_length=4; pin+=msg.digit; if(pin.length()==pin_length) { bank.send(verify_pin(account,pin,incoming)); state=&atm::verifying_pin; } } ) .handle( [&](clear_last_pressed const& msg) { if(!pin.empty()) { pin.pop_back(); } } ) .handle( [&](cancel_pressed const& msg) { state=&atm::done_processing; } ); } void waiting_for_card() { interface_hardware.send(display_enter_card()); incoming.wait() .handle( [&](card_inserted const& msg) { account=msg.account; pin=""; interface_hardware.send(display_enter_pin()); state=&atm::getting_pin; } ); } void done_processing() { interface_hardware.send(eject_card()); state=&atm::waiting_for_card; } atm(atm const&)=delete; atm& operator=(atm const&)=delete; public: atm(messaging::sender bank_, messaging::sender interface_hardware_): bank(bank_),interface_hardware(interface_hardware_) {} void done() { get_sender().send(messaging::close_queue()); } void run() { state=&atm::waiting_for_card; try { for(;;) { (this->*state)(); } } catch(messaging::close_queue const&) { } } messaging::sender get_sender() { return incoming; } };