%% @author Rolong
-module(process3).
-compile(export_all).
-define(I(F), io:format(F++"~n", [])).
-define(I(F, A), io:format(F++"~n", A)).
%%'TEST
%% vim cmd: '<,'>s/\([PE]\)3/\14/g
test1() ->
P1 = process3:start(fun1),
E1 = process3:on_exit(P1),
utils:sleep(100),
exit(P1, kill),
utils:sleep(100),
chk_alive("[kill P1] P1", P1),
chk_alive("[kill P1] E1", E1),
P2 = process3:start(fun1),
E2 = process3:on_exit(P2),
utils:sleep(100),
exit(P2, normal),
utils:sleep(100),
chk_alive("[normal P2] P2", P2),
chk_alive("[normal P2] E2", E2),
P3 = process3:start(fun1),
E3 = process3:on_exit(P3),
utils:sleep(100),
exit(E3, kill),
utils:sleep(100),
chk_alive("[kill E3] P3", P3),
chk_alive("[kill E3] E3", E3),
P4 = process3:start(fun1),
E4 = process3:on_exit(P4),
utils:sleep(100),
exit(E4, normal),
utils:sleep(100),
chk_alive("[normal E4] P4", P4),
chk_alive("[normal E4] E4", E4),
ok.
test2() ->
P1 = process3:start(fun1),
E1 = process3:on_exit(P1),
utils:sleep(100),
exit(P1, stop),
utils:sleep(100),
chk_alive("[stop P1] P1", P1),
chk_alive("[stop P1] E1", E1),
P2 = process3:start(fun1),
E2 = process3:on_exit(P2),
utils:sleep(100),
exit(P2, normal),
utils:sleep(100),
chk_alive("[normal P2] P2", P2),
chk_alive("[normal P2] E2", E2),
P3 = process3:start(fun1),
E3 = process3:on_exit(P3),
utils:sleep(100),
exit(E3, stop),
utils:sleep(100),
chk_alive("[stop E3] P3", P3),
chk_alive("[stop E3] E3", E3),
P4 = process3:start(fun1),
E4 = process3:on_exit(P4),
utils:sleep(100),
exit(E4, normal),
utils:sleep(100),
chk_alive("[normal E4] P4", P4),
chk_alive("[normal E4] E4", E4),
ok.
%%.
on_exit(Pid) ->
spawn(fun() ->
process_flag(trap_exit, true),
link(Pid),
on_exit_fun()
end).
on_exit_fun() ->
receive
{'EXIT', Pid, Reason} ->
?I("Exit signal from ~p, Reason:~p", [Pid, Reason]),
on_exit_fun();
Msg ->
?I("on_exit_fun receive: ~p", [Msg]),
on_exit_fun()
end.
start(Fun) ->
spawn(?MODULE,Fun,[]).
fun1() ->
receive
stop -> ok;
Msg ->
?I("fun1 receive: ~p", [Msg]),
fun1()
end.
%% ========= Internal Functions =========
chk_alive(Name, Pid) ->
case erlang:is_process_alive(Pid) of
true ->
io:format("~s(~p) is alive.~n", [Name, Pid]);
false ->
io:format("~s(~p) is NOT alive.~n", [Name, Pid])
end.
%% exit函数 文档
%%
%% exit(Pid, Reason) -> true
%% Pid = pid()
%% Reason = term()
%% Sends an exit signal with exit reason Reason to the process Pid.
%%
%% The following behavior apply if Reason is any term except normal or kill:
%%
%% If Pid is not trapping exits, Pid itself will exit with exit reason Reason. If Pid is trapping exits, the exit signal is transformed into a message {'EXIT', From, Reason} and delivered to the message queue of Pid. From is the pid of the process which sent the exit signal. See also process_flag/2.
%%
%% If Reason is the atom normal, Pid will not exit. If it is trapping exits, the exit signal is transformed into a message {'EXIT', From, normal} and delivered to its message queue.
%%
%% If Reason is the atom kill, that is if exit(Pid, kill) is called, an untrappable exit signal is sent to Pid which will unconditionally exit with exit reason killed.
%% vim: set filetype=erlang foldmarker=%%',%%. foldmethod=marker:
Erlang入门:进程实例操作与练习3(选修)
最新推荐文章于 2021-02-09 10:07:11 发布