Параллельное программирование на С++ в действии — страница 44 из 53

};


Листинг С.8. Конечный автомат банка

class bank_machine {

 messaging::receiver incoming;

 unsigned balance;


public:

 bank_machine():

  balance(199) {}


 void done() {

  get_sender().send(messaging::close_queue());

 }


 void run() {

  try {

   for (;;) {

    incoming.wait().handle(

     [&](verify_pin const& msg) {

      if (msg.pin == "1937") {

       msg.atm_queue.send(pin_verified());

      } else {

       msg.atm_queue.send(pin_incorrect());

      }

     }

    ).handle(

     [&](withdraw const& msg) {

      if (balance >= msg.amount) {

       msg.atm_queue.send(withdraw_ok());

       balance -= msg.amount;

      } else {

       msg.atm_queue.send(withdraw_denied());

      }

     }

    ).handle(

     [&](get_balance const& msg) {

      msg.atm_queue.send(::balance(balance));

     }

    ).handle(

     [&](withdrawal_processed const& msg) {

     }

    ).handle(

     [&](cancel_withdrawal const& msg) {

     }

    );

   }

  } catch(messaging::close_queue const&) {

  }

 }


 messaging::sender get_sender() {

  return incoming;

 }

};


Листинг С.9. Конечный автомат пользовательского интерфейса

class interface_machine {

 messaging::receiver incoming;


public:

 void done() {

  get_sender().send(messaging::close_queue());

 }


 void run() {

  try {

   for (;;) {

    incoming.wait().handle (

     [&](issue_money const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Issuing "

<< msg.amount << std::endl;

      }

     }

    ).handle(

     [&](display_insufficient_funds const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Insufficient funds" << std::endl;

      }

     }

    ).handle(

     [&](display_enter_pin const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout

<< "Please enter your PIN (0-9)" << std::endl;

      }

     }

    ).handle(

     [&](display_enter_card const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Please enter your card (I)"

<< std::endl;

      }

     }

    ).handle(

     [&](display_balance const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout

<< "The balance of your account is "

<< msg.amount << std::endl;

      }

     }

    ).handle(

     [&](display_withdrawal_options const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Withdraw 50? (w)" << std::endl;

       std::cout << "Display Balance? (b)"

<< std::endl;

       std::cout << "Cancel? (c) " << std::endl;

      }

     }

    ).handle(

     [&](display_withdrawal_cancelled const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Withdrawal cancelled"

<< std::endl;

      }

     }

    ).handle(

     [&](display_pin_incorrect_message const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "PIN incorrect" << std::endl;

      }

     }

    ).handle(

     [&](eject_card const& msg) {

      {

       std::lock_guard lk(iom);

       std::cout << "Ejecting card" << std::endl;

      }

     }

    );

   }

  } catch (messaging::close_queue&) {

  }

 }


 messaging::sender get_sender() {

  return incoming;

 }

};


Листинг С.10. Управляющая программа

int main() {

 bank_machine bank;

 interface_machine interface_hardware;


 atm machine(bank.get_sender(), interface_hardware.get_sender());


 std::thread bank_thread(&bank_machine::run, &bank);

 std::thread if_thread(&interface_machine::run,

&interface_hardware);

 std::thread atm_thread(&atm::run, &machine);


 messaging::sender atmqueue(machine.get_sender());