liveBook · Manning

Finite-state machine

As explained in C++ Concurrency in Action, Second Edition

A finite state machine is a computational model with a finite set of states and transitions triggered by inputs or events.

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

Figure 4.3. A simple state machine model for an ATM

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

How C++ Concurrency in Action, Second Edition covers it

How deep it goes
Explains state-dependent message handling through ATM code, without formalizing the complete machine.
Examples
Uses ATM interactions, including card insertion, PIN entry, correction, and cancellation.
What you can do after
Apply it by modeling a thread’s behavior as state-dependent message handling with possible outgoing messages.
How it connects
Connects finite-state machines to message passing, communicating sequential processes, and shared-data concurrency.

Also explained in

Compare how 9 books explain finite-state machine →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C++ Concurrency in Action, Second Edition. The section links point to the parts of the book it draws on.