ソースを参照

gen_srv修改

master
AICells 4年前
コミット
4a9ba94828
1個のファイルの変更82行の追加232行の削除
  1. +82
    -232
      src/gen_srv.erl

+ 82
- 232
src/gen_srv.erl ファイルの表示

@ -38,6 +38,16 @@
-define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))).
%% debug
-define(NOT_DEBUG, []).
-define(SYS_DEBUG(Debug, Name, Msg),
case Debug of
?NOT_DEBUG ->
Debug;
_ ->
sys:handle_debug(Debug, fun print_event/3, Name, Msg)
end).
-callback init(Args :: term()) ->
{ok, State :: term()} |
@ -46,7 +56,7 @@
ignore.
-callback handleCall(Request :: term(), From :: {pid(), Tag :: term()}, State :: term()) ->
-callback handleCall(Request :: term(), State :: term(), From :: {pid(), Tag :: term()}) ->
{reply, Reply :: term(), NewState :: term()} |
{reply, Reply :: term(), NewState :: term(), action() | action()} |
{noreply, NewState :: term()} |
@ -83,7 +93,9 @@
Status :: term().
-optional_callbacks([
handleInfo/2
handleCall/3
, handleCast/2
, handleInfo/2
, handleAfter/2
, terminate/2
, code_change/3
@ -456,7 +468,7 @@ rec_nodes_rest(_Tag, [], _Name, Badnodes, Replies) ->
%% Callback functions for system messages handling.
%%-----------------------------------------------------------------
system_continue(Parent, Debug, [Name, State, Module, Time, HibernateAfterTimeout]) ->
loopEntry(Time, Parent, Name, State, Module, HibernateAfterTimeout, Debug).
receiveIng(Time, Parent, Name, State, Module, HibernateAfterTimeout, Debug).
-spec system_terminate(_, _, _, [_]) -> no_return().
@ -512,7 +524,7 @@ init_it(Starter, Parent, ServerRef, Module, Args, Options) ->
case doModuleInit(Module, Args) of
{ok, State} ->
proc_lib:init_ack(Starter, {ok, self()}),
loopEntry(Parent, Name, Module, HibernateAfterTimeout, State, Debug, #{});
receiveIng(Parent, Name, Module, HibernateAfterTimeout, State, Debug, #{}, false);
{ok, State, Action} ->
proc_lib:init_ack(Starter, {ok, self()}),
loopEntry(Parent, Name, Module, HibernateAfterTimeout, State, Debug, #{}, Action);
@ -564,9 +576,12 @@ enter_loop(Module, State, Opts, ServerName, Action) ->
Parent = gen:get_parent(),
Debug = gen:debug_options(Name, Opts),
HibernateAfterTimeout = gen:hibernate_after(Opts),
loopEntry(Parent, Name, State, Module, HibernateAfterTimeout, Debug, #{}, Action).
loopEntry(Parent, Name, Module, HibernateAfterTimeout, State, Debug, #{}, Action).
loopEntry(Parent, Name, State, Module, HibernateAfterTimeout, Debug, Timers, Action) ->
ok.
loopEntry(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers) ->
receiveIng(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, IsHib) ->
receive
Msg ->
case Msg of
@ -584,257 +599,92 @@ loopEntry(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers)
end;
{system, PidFrom, Request} ->
%% system_continue/3
sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, [Name, CurState, Module, Time, HibernateAfterTimeout], Hib);
sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, [Name, Module, HibernateAfterTimeout, CurState, Timers], IsHib);
{'EXIT', Parent, Reason} ->
terminate(Reason, Reason, ?STACKTRACE(), Name, Module, CurState, Debug, Timers);
terminate(Reason, Reason, ?STACKTRACE(), Name, Module, CurState, Debug, Timers, Msg);
_ ->
matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, Msg)
end
after HibernateAfterTimeout ->
proc_lib:hibernate(?MODULE, wakeupFromHib, [CycleData, Module, CurStatus, CurState, Debug, IsHib])
proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout,CurState, Debug, Timers])
end.
loopEntry(hibernate, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
proc_lib:hibernate(?MODULE, wake_hib, [Parent, Name, State, Module, HibernateAfterTimeout, Debug]);
loopEntry({doAfter, Continue} = Msg, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Reply = try_dispatch(Module, handleAfter, Continue, State),
case Debug of
[] ->
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module,
HibernateAfterTimeout, State);
_ ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, Msg),
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module,
HibernateAfterTimeout, State, Debug1)
end;
loopEntry(Time, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Msg =
receive
Input ->
Input
after Time ->
timeout
end,
decode_msg(Msg, Parent, Name, State, Module, Time, HibernateAfterTimeout, Debug, false).
loopEntry(infinity, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
receive
Msg ->
decode_msg(Msg, Parent, Name, State, Module, infinity, HibernateAfterTimeout, Debug, false)
after HibernateAfterTimeout ->
loopEntry(hibernate, Parent, Name, State, Module, HibernateAfterTimeout, Debug)
end;
loopEntry(hibernate, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
proc_lib:hibernate(?MODULE, wake_hib, [Parent, Name, State, Module, HibernateAfterTimeout, Debug]);
loopEntry({doAfter, Continue} = Msg, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Reply = try_dispatch(Module, handleAfter, Continue, State),
case Debug of
[] ->
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module,
HibernateAfterTimeout, State);
_ ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name, Msg),
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module,
HibernateAfterTimeout, State, Debug1)
end;
loopEntry(Time, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Msg =
receive
Input ->
Input
after Time ->
timeout
end,
decode_msg(Msg, Parent, Name, State, Module, Time, HibernateAfterTimeout, Debug, false).
wakeupFromHib(Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Msg = receive
Input ->
Input
end,
decode_msg(Msg, Parent, Name, State, Module, hibernate, HibernateAfterTimeout, Debug, true).
decode_msg(Msg, Parent, Name, State, Module, Time, HibernateAfterTimeout, Debug, Hib) ->
case Msg of
{system, From, Req} ->
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
[Name, State, Module, Time, HibernateAfterTimeout], Hib);
{'EXIT', Parent, Reason} ->
terminate(Reason, ?STACKTRACE(), Name, undefined, Msg, Module, State, Debug);
_Msg when Debug =:= [] ->
handle_msg(Msg, Parent, Name, State, Module, HibernateAfterTimeout);
_Msg ->
Debug1 = sys:handle_debug(Debug, fun print_event/3,
Name, {in, Msg}),
handle_msg(Msg, Parent, Name, State, Module, HibernateAfterTimeout, Debug1)
matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, From, Request) ->
MsgEvent = {{call, From}, Request},
NewDebug = ?SYS_DEBUG(Debug, Name, {in, MsgEvent}),
try Module:handleCall(Request, CurState, From) of
Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, From)
catch
throw:Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, From);
Class:Reason:Stacktrace ->
terminate(Class, Reason, Stacktrace, Name, Module, CurState, NewDebug, Timers, MsgEvent)
end.
%% ---------------------------------------------------
%% Helper functions for try-catch of callbacks.
%% Returns the return value of the callback, or
%% {'EXIT', Class, Reason, Stack} (if an exception occurs)
%%
%% The Class, Reason and Stack are given to erlang:raise/3
%% to make sure proc_lib receives the proper reasons and
%% stacktraces.
%% ---------------------------------------------------
try_dispatch({'$gen_cast', Msg}, Module, State) ->
try_dispatch(Module, handle_cast, Msg, State);
try_dispatch(Info, Module, State) ->
try_dispatch(Module, handle_info, Info, State).
try_dispatch(Module, Func, Msg, State) ->
try
{ok, Module:Func(Msg, State)}
matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, Cast) ->
MsgEvent = {cast, Cast},
NewDebug = ?SYS_DEBUG(Debug, Name, {in, MsgEvent}),
try Module:handleCast(Cast, CurState) of
Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, false)
catch
throw:R ->
{ok, R};
error:undef = R:Stacktrace when Func == handle_info ->
case erlang:function_exported(Module, handle_info, 2) of
false ->
?LOG_WARNING(
#{label=>{gen_server, no_handle_info},
module=>Module,
message=>Msg},
#{domain=>[otp],
report_cb=>fun gen_server:format_log/2,
error_logger=>
#{tag=>warning_msg,
report_cb=>fun gen_server:format_log/1}}),
{ok, {noreply, State}};
true ->
{'EXIT', error, R, Stacktrace}
end;
Class:R:Stacktrace ->
{'EXIT', Class, R, Stacktrace}
throw:Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, false);
Class:Reason:Stacktrace ->
terminate(Class, Reason, Stacktrace, Name, Module, CurState, NewDebug, Timers, MsgEvent)
end.
try_handle_call(Module, Msg, From, State) ->
try
{ok, Module:handle_call(Msg, From, State)}
matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, Msg) ->
MsgEvent = {info, Msg},
NewDebug = ?SYS_DEBUG(Debug, Name, {in, MsgEvent}),
try Module:handleInfo(Msg, CurState) of
Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, false)
catch
throw:R ->
{ok, R};
Class:R:Stacktrace ->
{'EXIT', Class, R, Stacktrace}
throw:Result ->
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, Result, false);
Class:Reason:Stacktrace ->
terminate(Class, Reason, Stacktrace, Name, Module, CurState, NewDebug, Timers, MsgEvent)
end.
try_terminate(Module, Reason, State) ->
case erlang:function_exported(Module, terminate, 2) of
true ->
try
{ok, Module:terminate(Reason, State)}
catch
throw:R ->
{ok, R};
Class:R:Stacktrace ->
{'EXIT', Class, R, Stacktrace}
end;
false ->
{ok, ok}
doAfterCall(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, TimeoutEvent, IsHib, Args) ->
MsgEvent = {doAfter, Args},
NewDebug = ?SYS_DEBUG(Debug, Name, {in, MsgEvent}),
try Module:handleAfter(Args, CurState) of
Result ->
handleAR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, TimeoutEvent, IsHib, Result)
catch
throw:Result ->
handleAR(Parent, Name, Module, HibernateAfterTimeout, CurState, NewDebug, Timers, TimeoutEvent, IsHib, Result);
Class:Reason:Stacktrace ->
terminate(Class, Reason, Stacktrace, Name, Module, CurState, NewDebug, Timers, MsgEvent)
end.
%%% ---------------------------------------------------
%%% Message handling functions
%%% ---------------------------------------------------
handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Module, HibernateAfterTimeout) ->
Result = try_handle_call(Module, Msg, From, State),
handleCR(Parent, Name, Module, HibernateAfterTimeout, CurState, Debug, Timers, Result, From) ->
case Result of
{ok, {reply, Reply, NState}} ->
{noreply, NewState} ->
receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewState, Debug, Timers, false);
{reply, Reply, NewState} ->
reply(From, Reply),
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {reply, Reply, NState, Time1}} ->
reply(From, Reply),
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {noreply, NState}} ->
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {noreply, NState, Time1}} ->
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {stop, Reason, Reply, NState}} ->
try
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Module, NState, [])
after
reply(From, Reply)
end;
Other -> handle_common_reply(Other, Parent, Name, From, Msg, Module, HibernateAfterTimeout, State)
end;
handle_msg(Msg, Parent, Name, State, Module, HibernateAfterTimeout) ->
Reply = try_dispatch(Msg, Module, State),
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module, HibernateAfterTimeout, State).
handle_msg({'$gen_call', From, Msg}, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Result = try_handle_call(Module, Msg, From, State),
case Result of
{ok, {reply, Reply, NState}} ->
Debug1 = reply(Name, From, Reply, NState, Debug),
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {reply, Reply, NState, Time1}} ->
Debug1 = reply(Name, From, Reply, NState, Debug),
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {noreply, NState}} ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {noreply, NState, Time1}} ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {stop, Reason, Reply, NState}} ->
try
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Module, NState, Debug)
after
_ = reply(Name, From, Reply, NState, Debug)
end;
Other ->
handle_common_reply(Other, Parent, Name, From, Msg, Module, HibernateAfterTimeout, State, Debug)
end;
handle_msg(Msg, Parent, Name, State, Module, HibernateAfterTimeout, Debug) ->
Reply = try_dispatch(Msg, Module, State),
handle_common_reply(Reply, Parent, Name, undefined, Msg, Module, HibernateAfterTimeout, State, Debug).
handle_common_reply(Reply, Parent, Name, From, Msg, Module, HibernateAfterTimeout, State) ->
case Reply of
{ok, {noreply, NState}} ->
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {noreply, NState, Time1}} ->
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, []);
{ok, {stop, Reason, NState}} ->
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Module, NState, []);
{'EXIT', Class, Reason, Stacktrace} ->
terminate(Class, Reason, Stacktrace, Name, From, Msg, Module, State, []);
{ok, BadReply} ->
terminate({bad_return_value, BadReply}, ?STACKTRACE(), Name, From, Msg, Module, State, [])
NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From, NewState}),
receiveIng(Parent, Name, Module, HibernateAfterTimeout, NewState, NewDebug, Timers, false);
{noreply, NewState , Action } ->
loopEntry(Parent, Name, Module, HibernateAfterTimeout, NewState, Debug, Timers, Action);
{stop, Reason, NewState} ->
terminate(exit, Reason, ?STACKTRACE(), Name, Module, NewState, Debug, Timers, );
ok;
{reply, Reply, NewState, Action} ->
ok;
{stop, Reason, Reply, NewState} ->
ok
end.
handle_common_reply(Reply, Parent, Name, From, Msg, Module, HibernateAfterTimeout, State, Debug) ->
case Reply of
{ok, {noreply, NState}} ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loopEntry(infinity, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {noreply, NState, Time1}} ->
Debug1 = sys:handle_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loopEntry(Time1, Parent, Name, NState, Module, HibernateAfterTimeout, Debug1);
{ok, {stop, Reason, NState}} ->
terminate(Reason, ?STACKTRACE(), Name, From, Msg, Module, NState, Debug);
{'EXIT', Class, Reason, Stacktrace} ->
terminate(Class, Reason, Stacktrace, Name, From, Msg, Module, State, Debug);
{ok, BadReply} ->
terminate({bad_return_value, BadReply}, ?STACKTRACE(), Name, From, Msg, Module, State, Debug)
end.
reply(Name, From, Reply, State, Debug) ->
reply(From, Reply),
sys:handle_debug(Debug, fun print_event/3, Name,
{out, Reply, From, State}).
sys:handle_debug(Debug, fun print_event/3, Name, {out, Reply, From, State}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% timer deal start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
loopTimeoutsList([], Timers, _CycleData, Debug, TimeoutEvents) ->

読み込み中…
キャンセル
保存