Erlang OTP: Distributed & Fault-Tolerant Systems Programming · Lekcja

GenStatem do zarządzania stanem

Opanuj GenStatem, aby budować niezawodne maszyny stanów skończonych, zarządzać złożonymi przejściami stanów i skutecznie obsługiwać zdarzenia.

Lekcja 1 z 411 kroki

GenStatem do zarządzania stanem to bezpłatna lekcja Erlang OTP: Distributed & Fault-Tolerant Systems Programming na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Erlang OTP: Distributed & Fault-Tolerant Systems Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Erlang OTP: Distributed & Fault-Tolerant Systems Programming zawiera 4 lekcji w sumie.

Części tej lekcji nie zostały jeszcze przetłumaczone i są wyświetlane po angielsku.

Meet GenStatem

Welcome to GenStatem! It's an OTP behavior in Erlang used to build Finite State Machines (FSMs). If your system component needs to behave differently based on its current state, GenStatem is your friend.

Think of it as a specialized tool for managing complex state logic, offering more explicit control over state transitions than a regular GenServer.

FSM Fundamentals

A Finite State Machine (FSM) is a mathematical model of computation that describes the behavior of a system. It can only be in one state at any given time.

  • States: Distinct conditions a system can be in (e.g., "on", "off", "idle", "active").
  • Events: Inputs or occurrences that trigger a change in state (e.g., "button_press", "timeout").
  • Transitions: Rules that define how an event in a particular state causes a shift to a new state.

GenStatem Module Basics

Like other OTP behaviors, GenStatem requires a callback module. This module implements specific functions that define the FSM's behavior.

The most basic function is init/1, which sets up the initial state and data for your FSM. It returns {:ok, InitialState, InitialStateData}.

-module(my_fsm).
-behaviour(gen_statem).

-export([start_link/0]).
-export([init/1]).
-export([callback_mode/0]).

% Minimal init for a GenStatem
init(_Args) ->
    io:format("FSM initializing...~n"),
    InitialState = off, % Our first state
    InitialStateData = [], % Any data we want to carry
    {:ok, InitialState, InitialStateData}.

% Defines how events are handled (state-name based)
callback_mode() ->
    state_functions.

start_link() ->
    gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).

States and StateData

In GenStatem, a state is typically an atom (e.g., :on, :off). StateData is any Erlang term that holds the internal information associated with the current state, similar to a GenServer's state.

When you transition, you specify both the new state atom and the new state data. This allows you to carry context and information across different states of your FSM.

Responding to Events

GenStatem uses callback functions to react to events. For asynchronous events (like gen_statem:cast/2), the handle_event/4 callback is used.

The function signature is State(EventType, EventContent, StateData), where State is the current state atom and EventType indicates the type of message (e.g., :cast, :info).

% Example for 'off' state
off(cast, toggle, StateData) ->
    io:format("Switching to ON from OFF~n"),
    {:next_state, on, StateData}; % Transition to 'on' state

off(info, _Msg, StateData) ->
    io:format("Received info in OFF state~n"),
    {:next_state, off, StateData}.

Changing States

The return value of your event-handling functions dictates the FSM's next action. To change state, you return a tuple: {:next_state, NewState, NewStateData}.

  • NewState: The atom representing the next state.
  • NewStateData: The updated state data to be carried into the new state.

If you want to stay in the current state, you can return {:keep_state, NewStateData} or {:keep_state_and_data} if data doesn't change.

Sync vs. Async Events

GenStatem handles different types of events:

  • handle_call/4: For synchronous calls (gen_statem:call/3). The caller waits for a reply.
  • handle_event/4: For asynchronous casts (gen_statem:cast/2) and internal messages (gen_statem:info/2, or process messages). The caller does not wait.
  • handle_info/4: A specialized version of handle_event for process messages not originating from gen_statem:cast or gen_statem:call. Often less used with state_functions mode.

We'll focus on handle_call and handle_event in our example.

Light Switch Example

Let's build a classic FSM: a light switch! It will have two states: off and on.

We'll send a toggle event to change its state. We'll also add a way to check its current status.

Light Switch Code

Here's the full Erlang module for our light switch. Run it and try interacting with it!

-module(light_switch).
-behaviour(gen_statem).

-export([start_link/0, toggle/0, status/0]).
-export([init/1, callback_mode/0]).
-export([off/4, on/4]). % Export state functions

% -- Public API --
start_link() ->
    gen_statem:start_link({local, ?MODULE}, ?MODULE, [], []).

toggle() ->
    gen_statem:cast(?MODULE, toggle).

status() ->
    gen_statem:call(?MODULE, status).

% -- GenStatem Callbacks --
init(_Args) ->
    io:format("Light switch initializing to OFF~n"),
    {:ok, off, []}. % Initial state 'off', no specific data

callback_mode() ->
    state_functions.

% -- State 'off' callbacks --
off(cast, toggle, StateData) ->
    io:format("Switching from OFF to ON~n"),
    {:next_state, on, StateData};
off(call, status, From, StateData) ->
    gen_statem:reply(From, off),
    {:keep_state, StateData};
off(EventType, EventContent, StateData) ->
    io:format("OFF state received unhandled event: ~p, ~p~n", [EventType, EventContent]),
    {:keep_state, StateData}.

% -- State 'on' callbacks --
on(cast, toggle, StateData) ->
    io:format("Switching from ON to OFF~n"),
    {:next_state, off, StateData};
on(call, status, From, StateData) ->
    gen_statem:reply(From, on),
    {:keep_state, StateData};
on(EventType, EventContent, StateData) ->
    io:format("ON state received unhandled event: ~p, ~p~n", [EventType, EventContent]),
    {:keep_state, StateData}.

% --- How to run this code in Erlang shell: ---
% c(light_switch).
% light_switch:start_link().
% light_switch:status(). % Should be 'off'
% light_switch:toggle().
% light_switch:status(). % Should be 'on'
% light_switch:toggle().
% light_switch:status(). % Should be 'off'

GenStatem Challenge

Consider a GenStatem module representing a door with states :closed and :open. It receives :open_door and :close_door events.

If the door is :closed and receives :open_door, it transitions to :open. If it's :open and receives :close_door, it transitions to :closed.

What is the correct return value from the closed/4 state function when it receives an :open_door event via gen_statem:cast/2?

GenStatem Summary

Great job mastering GenStatem!

You've learned that GenStatem is ideal for implementing Finite State Machines, allowing you to manage complex state-dependent logic. Key takeaways:

  • FSMs have states, events, and transitions.
  • GenStatem uses callback modules and state functions (e.g., off/4, on/4).
  • You transition between states using {:next_state, NewState, NewStateData}.
  • Events can be asynchronous (cast, handled by handle_event/4) or synchronous (call, handled by handle_call/4).

This powerful behavior is a cornerstone for building robust, predictable systems in Erlang.

Bezpłatny start

Ucz się Erlang dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
12
Lekcje
48

Często zadawane pytania

Czy lekcja „GenStatem do zarządzania stanem” jest bezpłatna?

Tak — pełny tekst „GenStatem do zarządzania stanem” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Erlang OTP: Distributed & Fault-Tolerant Systems Programming, przejdź na CoddyKit PRO. Kurs Erlang OTP: Distributed & Fault-Tolerant Systems Programming zawiera 4 lekcji w sumie.

Co nauczysz się w „GenStatem do zarządzania stanem”?

Opanuj GenStatem, aby budować niezawodne maszyny stanów skończonych, zarządzać złożonymi przejściami stanów i skutecznie obsługiwać zdarzenia. Ćwiczysz Erlang OTP: Distributed & Fault-Tolerant Systems Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Erlang OTP: Distributed & Fault-Tolerant Systems Programming?

Nie wymagamy żadnego doświadczenia. Erlang OTP: Distributed & Fault-Tolerant Systems Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „GenStatem do zarządzania stanem”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Erlang OTP: Distributed & Fault-Tolerant Systems Programming?

Tak. Każda lekcja Erlang OTP: Distributed & Fault-Tolerant Systems Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. GenStatem do zarządzania stanem
  2. GenEvent do obsługi zdarzeń
  3. Niestandardowe behaviors OTP
  4. Wymiana kodu na gorąco i aktualizacje działających systemów
← Powrót do Erlang OTP: Distributed & Fault-Tolerant Systems Programming