2017-11-02 28 views
1

나는 Erlang에서 새로운 학습자입니다. Erlang 변수의 수명주기에 대해 질문이 있습니다.gen_server의 주 생명주기는 무엇입니까

-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}). 

변수 "국가"수명주기는 무엇입니까 Erlang gen_server comunication에서

참조?

변수 "State"가 handle_call 및 handle_cast에서 재사용되는 것을 볼 수 있습니다. 우선,이 "상태"는 init() 함수 "#state{id = Name, m = M}"에서 초기화되는 동일한 상태입니까?

그렇다면 "상태"가 전역 변수입니까? 이 "국가"는 언제 파괴 될 것입니까?

얼랭에는 전역 변수가 있습니까?

답변

4

당신의 직관은 정확합니다. 각 콜백 (즉, inti/1, handle_call/3 등)은 State을 매개 변수로 사용하며 결과의 일부로 (아마도 새로운) State을 반환해야합니다.

어떻게 작동하는지 이해하려면 gen_server이 무엇인지 알아야합니다. 당신이 gen_server:start_link/4를 호출 할 때 슈퍼 매우-과도하게 단순화 방법으로, 어떤 gen_server을하고있는 것은 :

% 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 

당신이 볼 수 있듯이이의 State의 값이 gen_server 과정에 지역, 그것은 각 콜백에 전달되고, 으로 바뀌며 각 콜백의 결과는 서버가 종료 될 때까지 계속 반복됩니다. 물론 gen_server의 코드는 그렇게 간단하지 않습니다. (This talk은 스페인어에 대해 큰 도움이됩니다.

희망이 있습니다.

+0

감사합니다. Brujo. 나는 한 가지 더 질문을하고있다. 호출, 캐스트, 정보, 다른 프로세스에서 동시에 상태를 설정하면 상태가 다른 프로세스의 모든 변경 사항을 캡처합니까? cast()가 값 A를 State로 설정하면, 동시에 다른 cast()는 값 B를 State로 설정합니다. 그 전에 State는 비어 있습니다. 값을 설정 한 후에 State, A, B 또는 AB에 저장 될 내용은 무엇입니까? @Brujo Benavides – Neil

+0

그래, 내 코드에서 볼 수 있듯이 메시지가 비동기 적으로 서버에 도달하더라도 루프는 오직 한 시간 만 처리하고 각 콜백의 평가는 동시 적입니다 (즉, 코드가 반환 될 때까지 코드가 이동하지 않습니다. 'handle_ *'에서). 또한 명백하게 말하면,'gen_server : cast/2'는 상태를 설정하지 않고 서버 프로세스로만 메시지를 보냅니다. 이 예제에서는'cast (Server, Msg) -> Server처럼 보일 것입니다! {cast, Ms}. " "Mod : handle_cast/2 "가 평가 될 때 그 메시지가 우리의'loop' 내에 수신됩니다. –

0

상태은 gen_server의 내부 상태입니다. State는 데이터 구조 (맵, 레코드 또는 목록)에 대한 단일 변수 (이 경우 레코드) 일 수 있습니다. 값 세트를 정의한 경우 레코드를 사용하십시오. 그렇지 않으면 맵을 사용할 수 있습니다.

예, 상태는 init() 함수에서 초기화되며 각 콜백의 매개 변수로 전달됩니다. 필요에 따라 State 값을 간단히 업데이트 할 수 있으며 각 콜백에서 응답을 보낼 때 설정은 새로운 상태로 설정됩니다.

gen 서버가 죽거나 정상적으로 종료되면 상태가 gen_server 프로세스와 함께 파괴됩니다. 이유와 함께 종료 할 때 정상 종료/3 콜백이 호출됩니다. 나는 그것이 변수 State 어디서나 같은 기술적으로 아니라고 지적 가치가 있다고 생각하지만 그것은 어디에서나 동일 을 참조 않지만