I am new learner on Erlang, I have questions about Erlang variable's life cycle.
Reference from Erlang gen_server comunication
-module(wy).
-compile(export_all).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-behaviour(gen_server).
-record(state, {id ,m, succ, pred}).
start(Name, M) ->
gen_server:start_link({local, Name}, ?MODULE, [Name, M], []).
init([Name, M]) ->
{ok, #state{id = Name, m = M}}.
handle_call({get_server_info}, _Frome, State) ->
{reply, State, State};
handle_call(_Request, _From, State) ->
Reply = ok,
{reply, Reply, State}.
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
get_server_info(ServerName) ->
gen_server:call(ServerName, {get_server_info}).
What is the Variable "State" life cycle?
We can see variable "State" is reused from handle_call and handle_cast. First of all, are these "State" is the same one which is initialized from init() function "#state{id = Name, m = M}"
?
If so, is this "State" a global variable? When will this "State" be destroyed.
Does Erlang have global variables?
Your intuition is correct, although I think it's worth pointing out that the variable State
is technically not the same everywhere but it does reference the same value everywhere. Each of your callbacks (i.e. inti/1
, handle_call/3
, etc.) receive State
as a parameter and they must return a (possibly new) State
as part of their results.
To understand how this works, you need to know what gen_server
does. In an super-extremely-oversimplified way, what gen_server is doing when you call gen_server:start_link/4
is:
% Ignoring stuff here, for simplicity
start_link(_Name, Mod, InitArg, _Options) ->
spawn(
fun() ->
{ok, State} = Mod:init(InitArg),
loop(Mod, State) %% This is where the result of your init/1 function goes
end).
loop(Mod, State) ->
NextState =
receive
{call, From, Msg} ->
% Here, it gives you the current state and expects you to return
% a new one.
{reply, Reply, NewState} = Mod:handle_call(Msg, From, State),
NewState;
{cast, Msg} ->
% Here, it gives you the current state and expects you to return
% a new one.
{noreply, NewState} = Mod:handle_cast(Msg, State),
NewState;
Info ->
% Here, it gives you the current state and expects you to return
% a new one.
{noreply, NewState} = Mod:handle_info(Msg, State),
NewState;
{stop, Reason} ->
Mod:terminate(Reason, State),
exit(Reason)
end,
loop(Mod, NextState). % Then it keeps on looping with the new state
As you can see, the value of the State
is local to the gen_server process, it is passed to each callback and it's replaced with the result of each callback to keep looping until the server is terminated.
Of course, gen_server's code is not that simple (This talk provides a great explanation for this - in Spanish, I know, sorry).
Hope this helps :)