Files
concurrency-in-action/source/listing_c.7.cpp
2018-10-18 00:40:34 -05:00

121 lines
3.8 KiB
C++

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>([&](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>([&](withdraw_denied const& msg) {
interface_hardware.send(display_insufficient_funds());
state = &atm::done_processing;
})
.handle<cancel_pressed>([&](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>([&](balance const& msg) {
interface_hardware.send(display_balance(msg.amount));
state = &atm::wait_for_action;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg) { state = &atm::done_processing; });
}
void wait_for_action()
{
interface_hardware.send(display_withdrawal_options());
incoming.wait()
.handle<withdraw_pressed>([&](withdraw_pressed const& msg) {
withdrawal_amount = msg.amount;
bank.send(withdraw(account, msg.amount, incoming));
state = &atm::process_withdrawal;
})
.handle<balance_pressed>([&](balance_pressed const& msg) {
bank.send(get_balance(account, incoming));
state = &atm::process_balance;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg) { state = &atm::done_processing; });
}
void verifying_pin()
{
incoming.wait()
.handle<pin_verified>(
[&](pin_verified const& msg) { state = &atm::wait_for_action; })
.handle<pin_incorrect>([&](pin_incorrect const& msg) {
interface_hardware.send(display_pin_incorrect_message());
state = &atm::done_processing;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg) { state = &atm::done_processing; });
}
void getting_pin()
{
incoming.wait()
.handle<digit_pressed>([&](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>([&](clear_last_pressed const& msg) {
if (!pin.empty()) {
pin.pop_back();
}
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg) { state = &atm::done_processing; });
}
void waiting_for_card()
{
interface_hardware.send(display_enter_card());
incoming.wait().handle<card_inserted>([&](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; }
};