A finite-state machine processes messages according to its current state: each message may update that state and trigger messages to other threads. A thread’s state machine can be explicit or implicit in the application’s structure. In message-passing designs, this lets each thread be reasoned about independently, provided threads do not share data. section 4.4.2
View the ATM diagram to see a concrete state-machine model. section 4.4.2
Listing 4.15. A simple implementation of an ATM logic class
struct card_inserted
{
std::string account;
};
class atm
{
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
std::string account;
std::string pin;
void waiting_for_card() #1
{
interface_hardware.send(display_enter_card()); #2
incoming.wait() #3
.handle<card_inserted>(
[&](card_inserted const& msg) #4
{
account=msg.account;
pin="";
interface_hardware.send(display_enter_pin());
state=&atm::getting_pin;
}
);
}
void getting_pin();
public:
void run() #5
{
state=&atm::waiting_for_card; #6
try
{
for(;;)
{
(this->*state)(); #7
}
}
catch(messaging::close_queue const&)
{
}
}
};
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":12,\"ch\":57},{\"line\":12,\"ch\":59}],[{\"line\":14,\"ch\":57},{\"line\":14,\"ch\":59}],[{\"line\":15,\"ch\":57},{\"line\":15,\"ch\":59}],[{\"line\":17,\"ch\":57},{\"line\":17,\"ch\":59}],[{\"line\":28,\"ch\":57},{\"line\":28,\"ch\":59}],[{\"line\":30,\"ch\":57},{\"line\":30,\"ch\":59}],[{\"line\":35,\"ch\":57},{\"line\":35,\"ch\":59}]]"}
!@%STYLE%@!
Inspect the ATM logic implementation, where a state selects which messages to handle. section 4.4.2
Listing 4.16. The getting_pin state function for the simple ATM implementation
void atm::getting_pin()
{
incoming.wait()
.handle<digit_pressed>( #1
[&](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>( #2
[&](clear_last_pressed const& msg)
{
if(!pin.empty())
{
pin.resize(pin.length()-1);
}
}
)
.handle<cancel_pressed>( #3
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
}
);
}
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":3,\"ch\":51},{\"line\":3,\"ch\":53}],[{\"line\":15,\"ch\":51},{\"line\":15,\"ch\":53}],[{\"line\":24,\"ch\":51},{\"line\":24,\"ch\":53}]]"}
!@%STYLE%@!
See how the PIN-entry state handles digits, correction, and cancellation. section 4.4.2








