各种有用的erlang行为
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

2466 行
111 KiB

4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
4 年前
  1. -module(gen_ipc).
  2. -compile(inline).
  3. -compile({inline_size, 128}).
  4. -include_lib("kernel/include/logger.hrl").
  5. -import(maps, [iterator/1, next/1]).
  6. -import(gen_call, [gcall/3, gcall/4, greply/2, try_greply/2]).
  7. -export([
  8. %% API for gen_server or gen_statem behaviour
  9. start/3, start/4, start_link/3, start_link/4
  10. , start_monitor/3, start_monitor/4
  11. , stop/1, stop/3
  12. , cast/2, send/2
  13. , abcast/2, abcast/3
  14. , call/2, call/3
  15. , send_request/2, wait_response/1, wait_response/2, receive_response/1, receive_response/2, check_response/2
  16. , multi_call/2, multi_call/3, multi_call/4
  17. , enter_loop/4, enter_loop/5, enter_loop/6
  18. , reply/1, reply/2
  19. %% API for gen_event behaviour
  20. , send_request/3
  21. , info_notify/2, call_notify/2
  22. , epm_call/3, epm_call/4, epm_info/3
  23. , add_epm/3, del_epm/3, add_sup_epm/3
  24. , swap_epm/3, swap_sup_epm/3
  25. , which_epm/1
  26. %% gen callbacks
  27. , init_it/6
  28. %% sys callbacks
  29. , system_continue/3
  30. , system_terminate/4
  31. , system_code_change/4
  32. , system_get_state/1
  33. , system_replace_state/2
  34. , format_status/2
  35. %% Internal callbacks
  36. , wakeupFromHib/12
  37. %% logger callback
  38. , format_log/1
  39. , format_log/2
  40. , epm_log/1
  41. ]).
  42. % 简写备注**********************************
  43. % isPostpone isPos
  44. % isHibernate isHib
  45. % nextEvent nextE
  46. % nextStatus nextS
  47. % keepStatus kpS
  48. % keepStatusState kpS_S
  49. % repeatStatus reS
  50. % repeatStatusState reS_S
  51. % *****************************************
  52. % %% timeout相关宏定义
  53. % -define(REL_TIMEOUT(T), ((is_integer(T) andalso (T) >= 0) orelse (T) =:= infinity)).
  54. % -define(ABS_TIMEOUT(T), (is_integer(T) orelse (T) =:= infinity)).
  55. -define(STACKTRACE(), element(2, erlang:process_info(self(), current_stacktrace))).
  56. -define(CB_FORM_ENTER, 1). %% 从enter 回调返回
  57. -define(CB_FORM_AFTER, 2). %% 从after 回调返回
  58. -define(CB_FORM_EVENT, 3). %% 从event 回调返回
  59. %% debug 调试相关宏定义
  60. -define(NOT_DEBUG, []).
  61. -define(SYS_DEBUG(Debug, Name, SystemEvent),
  62. case Debug of
  63. ?NOT_DEBUG ->
  64. Debug;
  65. _ ->
  66. sys:handle_debug(Debug, fun print_event/3, Name, SystemEvent)
  67. end).
  68. %%%==========================================================================
  69. %%% Interface functions.
  70. %%%==========================================================================
  71. %% gcall 发送消息来源进程格式类型
  72. -type from() :: {To :: pid(), Tag :: term()}.
  73. -type requestId() :: term().
  74. %% 事件类型
  75. -type eventType() :: externalEventType() | timeoutEventType() | {'onevent', Subtype :: term()}.
  76. -type externalEventType() :: {'call', From :: from()} | 'cast' | 'info'.
  77. -type timeoutEventType() :: GTimeoutName :: term() | 'eTimeout' | 'sTimeout'. %% 前面的GTimeoutName这个是通用超时标识名
  78. %% 是否捕捉信号 gen_event管理进程需要设置该参数为true
  79. -type isTrapExit() :: boolean().
  80. %% 是否允许进入enter 回调
  81. -type isEnter() :: boolean().
  82. %% 如果为 "true" 则推迟当前事件,并在状态更改时重试(=/=)
  83. -type isPos() :: boolean().
  84. %% 如果为 "true" 则使服务器休眠而不是进入接收状态
  85. -type isHib() :: boolean().
  86. %% 定时器相关
  87. -type timeouts() :: Time :: timeout() | integer().
  88. -type timeoutOption() :: {abs, Abs :: boolean()}.
  89. % gen_event模式下回调模块的标识
  90. -type epmHandler() :: atom() | {atom(), term()}.
  91. %% 在状态更改期间:
  92. %% NextStatus and NewData are set.
  93. %% 按照出现的顺序处理 actions()列表
  94. %% 这些action() 按包含列表中的出现顺序执行。设置选项的选项将覆盖任何以前的选项,因此每种类型的最后一种将获胜。
  95. %% 如果设置了enter 则进入enter回调
  96. %% 如果设置了doAfter 则进入after回调
  97. %% 如果 "postpone" 为 "true",则推迟当前事件。
  98. %% 如果设置了“超时”,则开始状态超时。 零超时事件将会插入到待处理事件的前面 先执行
  99. %% 如果有postponed 事件则 事件执行顺序为 超时添加和更新 + 零超时 + 当前事件 + 反序的Postpone事件 + LeftEvent
  100. %% 处理待处理的事件,或者如果没有待处理的事件,则服务器进入接收或休眠状态(当“hibernate”为“ true”时)
  101. -type initAction() ::
  102. {trap_exit, Bool :: isTrapExit()} | % 设置是否捕捉信息 主要用于gen_event模式下
  103. eventAction().
  104. -type eventAction() ::
  105. {'doAfter', Args :: term()} | % 设置执行某事件后是否回调 handleAfter
  106. {'isPos', Bool :: isPos()} | % 设置推迟选项
  107. {'nextE', EventType :: eventType(), EventContent :: term()} | % 插入事件作为下一个处理
  108. commonAction().
  109. -type afterAction() ::
  110. {'nextE', EventType :: eventType(), EventContent :: term()} | % 插入事件作为下一个处理
  111. commonAction().
  112. -type enterAction() ::
  113. {'isPos', false} | % 虽然enter action 不能设置postpone 但是可以取消之前event的设置
  114. commonAction().
  115. -type commonAction() ::
  116. {'isEnter', Bool :: isEnter()} |
  117. {'isHib', Bool :: isHib()} |
  118. timeoutAction() |
  119. replyAction().
  120. -type timeoutAction() ::
  121. timeoutNewAction() |
  122. timeoutCancelAction() |
  123. timeoutUpdateAction().
  124. -type timeoutNewAction() ::
  125. {'eTimeout', Time :: timeouts(), EventContent :: term()} | % Set the event_timeout option
  126. {'eTimeout', Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])} | % Set the event_timeout option
  127. {'sTimeout', Time :: timeouts(), EventContent :: term()} | % Set the status_timeout option
  128. {'sTimeout', Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])} | % Set the status_timeout option
  129. {'gTimeout', Name :: term(), Time :: timeouts(), EventContent :: term()} | % Set the generic_timeout option
  130. {'gTimeout', Name :: term(), Time :: timeouts(), EventContent :: term(), Options :: ([timeoutOption()])}. % Set the generic_timeout option
  131. -type timeoutCancelAction() ::
  132. 'c_eTimeout' | % 不可能也不需要更新此超时,因为任何其他事件都会自动取消它。
  133. 'c_sTimeout' |
  134. {'c_gTimeout', Name :: term()}.
  135. -type timeoutUpdateAction() ::
  136. {'u_eTimeout', EventContent :: term()} | % 不可能也不需要取消此超时,因为任何其他事件都会自动取消它。
  137. {'u_sTimeout', EventContent :: term()} |
  138. {'u_gTimeout', Name :: term(), EventContent :: term()}.
  139. -type actions(ActionType) ::
  140. ActionType |
  141. [ActionType, ...].
  142. -type replyAction() ::
  143. {'reply', From :: from(), Reply :: term()}.
  144. -type eventCallbackResult() ::
  145. {'reply', Reply :: term(), NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  146. {'sreply', Reply :: term(), NextStatus :: term(), NewState :: term()} | % 用作gen_ipc模式便捷式返回reply 而不用把reply放在actions列表中
  147. {'noreply', NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  148. {'reply', Reply :: term(), NewState :: term(), Options :: hibernate | {doAfter, Args :: term()}} | % 用作gen_server模式时快速响应进入消息接收
  149. {'sreply', Reply :: term(), NextStatus :: term(), NewState :: term(), Actions :: actions(eventAction())} | % 用作gen_ipc模式便捷式返回reply 而不用把reply放在actions列表中
  150. {'noreply', NewState :: term(), Options :: hibernate | {doAfter, Args :: term()}} | % 用作gen_server模式时快速响应进入循环
  151. {'nextS', NextStatus :: term(), NewState :: term()} | % {next_status,NextS,NewData,[]}
  152. {'nextS', NextStatus :: term(), NewState :: term(), Actions :: actions(eventAction())} | % Status transition, maybe to the same status
  153. commonCallbackResult(eventAction()).
  154. -type afterCallbackResult() ::
  155. {'nextS', NextStatus :: term(), NewState :: term()} | % {next_status,NextS,NewData,[]}
  156. {'nextS', NextStatus :: term(), NewState :: term(), Actions :: actions(afterAction())} | % Status transition, maybe to the same status
  157. {'noreply', NewState :: term()} | % 用作gen_server模式时快速响应进入消息接收
  158. {'noreply', NewState :: term(), Options :: hibernate} | % 用作gen_server模式时快速响应进入消息接收
  159. commonCallbackResult(afterAction()).
  160. -type enterCallbackResult() ::
  161. commonCallbackResult(enterAction()).
  162. -type commonCallbackResult(ActionType) ::
  163. {'kpS', NewState :: term()} | % {keep_status,NewData,[]}
  164. {'kpS', NewState :: term(), Actions :: actions(ActionType)} | % Keep status, change data
  165. 'kpS_S' | % {keep_status_and_data,[]}
  166. {'kpS_S', Actions :: [ActionType]} | % Keep status and data -> only actions
  167. {'reS', NewState :: term()} | % {repeat_status,NewData,[]}
  168. {'reS', NewState :: term(), Actions :: actions(ActionType)} | % Repeat status, change data
  169. 'reS_S' | % {repeat_status_and_data,[]}
  170. {'reS_S', Actions :: actions(ActionType)} | % Repeat status and data -> only actions
  171. 'stop' | % {stop,normal}
  172. {'stop', Reason :: term()} | % Stop the server
  173. {'stop', Reason :: term(), NewState :: term()} | % Stop the server
  174. {'stopReply', Reason :: term(), Replies :: replyAction() | [replyAction(), ...] | term()} | % Reply then stop the server
  175. {'stopReply', Reason :: term(), Replies :: replyAction() | [replyAction(), ...] | term(), NewState :: term()}. % Reply then stop the server
  176. %% 状态机的初始化功能函数
  177. %% 如果要模拟gen_server init返回定时时间 可以在Actions返回定时动作
  178. %% 如果要把改进程当做gen_event管理进程需要在actions列表包含 {trap_exit, true} 设置该进程捕捉异常
  179. -callback init(Args :: term()) ->
  180. 'ignore' |
  181. {'stop', Reason :: term()} |
  182. {'ok', State :: term()} |
  183. {'ok', Status :: term(), State :: term()} |
  184. {'ok', Status :: term(), State :: term(), Actions :: actions(initAction())}.
  185. %% 当 enter call 回调函数
  186. -callback handleEnter(OldStatus :: term(), CurStatus :: term(), State :: term()) ->
  187. enterCallbackResult().
  188. %% 当 init返回actions包含 doAfter 的时候会在 enter调用后 调用该函数 或者
  189. %% 在事件回调函数返回后 enter调用后调用该函数
  190. %% 该回调函数相当于 gen_server 的 handle_continue回调 但是在综合模式时 也可以生效
  191. -callback handleAfter(AfterArgs :: term(), Status :: term(), State :: term()) ->
  192. afterCallbackResult().
  193. %% call 所以状态的回调函数
  194. -callback handleCall(EventContent :: term(), Status :: term(), State :: term(), From :: {pid(), Tag :: term()}) ->
  195. eventCallbackResult().
  196. %% cast 回调函数
  197. -callback handleCast(EventContent :: term(), Status :: term(), State :: term()) ->
  198. eventCallbackResult().
  199. %% info 回调函数
  200. -callback handleInfo(EventContent :: term(), Status :: term(), State :: term()) ->
  201. eventCallbackResult().
  202. %% 内部事件 Onevent 包括actions 设置的定时器超时产生的事件 和 nextE产生的超时事件 但是不是 call cast info 回调函数 以及其他自定义定时事件 的回调函数
  203. %% 并且这里需要注意 其他erlang:start_timer生成超时事件发送的消息 不能和gen_ipc定时器关键字重合 有可能会导致一些问题
  204. -callback handleOnevent(EventType :: term(), EventContent :: term(), Status :: term(), State :: term()) ->
  205. eventCallbackResult().
  206. %% 在gen_event模式下 扩展了下面三个回调函数 考虑场景是:
  207. %% 比如游戏里的公会 有时候一个公会一个进程来管理可能开销比较高 只用一个进程来管理所以公会有可能一个进程处理不过来
  208. %% 这个时候可以考虑用gen_ipc来分组管理 一个gen_ipc进程管理 N 个公会 但是管理进程需要做一些数据保存什么 或者定时 就可能会用到下面的这些函数
  209. %% gen_event模式时 notify 有可能需要回调该管理进程的该函数
  210. -callback handleEpmEvent(EventContent :: term(), Status :: term(), State :: term()) ->
  211. eventCallbackResult().
  212. %% gen_event模式时 call请求 有可能需要回调该管理进程的该函数
  213. -callback handleEpmCall(EventContent :: term(), Status :: term(), State :: term()) ->
  214. eventCallbackResult().
  215. %% gen_event模式时 info消息 有可能需要回调该管理进程的该函数
  216. -callback handleEpmInfo(EventContent :: term(), Status :: term(), State :: term()) ->
  217. eventCallbackResult().
  218. %% 在服务器终止之前进行清理。
  219. -callback terminate(Reason :: 'normal' | 'shutdown' | {'shutdown', term()} | term(), Status :: term(), State :: term()) ->
  220. any().
  221. %% 代码更新回调函数
  222. -callback code_change(OldVsn :: term() | {'down', term()}, OldStatus :: term(), OldState :: term(), Extra :: term()) ->
  223. {ok, NewStatus :: term(), NewData :: term()} |
  224. (Reason :: term()).
  225. %% 以一种通常被精简的方式来格式化回调模块状态。
  226. %% 对于StatusOption =:= 'normal',首选返回 term 是[{data,[{"Status",FormattedStatus}]}]
  227. %% 对于StatusOption =:= 'terminate',它只是FormattedStatus
  228. -callback formatStatus(StatusOption, [PDict | term()]) ->
  229. Status :: term() when
  230. StatusOption :: 'normal' | 'terminate',
  231. PDict :: [{Key :: term(), Value :: term()}].
  232. -optional_callbacks([
  233. formatStatus/2
  234. , terminate/3
  235. , code_change/4
  236. , handleEnter/3
  237. , handleAfter/3
  238. , handleOnevent/4
  239. , handleEpmEvent/3
  240. , handleEpmCall/3
  241. , handleEpmInfo/3
  242. ]).
  243. -record(epmHer, {
  244. epmId = undefined :: term(),
  245. epmM :: atom(),
  246. epmSup = undefined :: 'undefined' | pid(),
  247. epmS :: term()
  248. }).
  249. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  250. -type serverName() ::
  251. {'local', atom()} |
  252. {'global', GlobalName :: term()} |
  253. {'via', RegMod :: module(), Name :: term()}.
  254. -type serverRef() ::
  255. pid() |
  256. (LocalName :: atom()) |
  257. {Name :: atom(), Node :: atom()} |
  258. {'global', GlobalName :: term()} |
  259. {'via', RegMod :: module(), ViaName :: term()}.
  260. -type startOpt() ::
  261. {'timeout', Time :: timeout()} |
  262. {'spawn_opt', [proc_lib:spawn_option()]} |
  263. enterLoopOpt().
  264. -type enterLoopOpt() ::
  265. {'debug', Debugs :: [sys:debug_option()]} |
  266. {'hibernate_after', HibernateAfterTimeout :: timeout()}.
  267. -type startRet() ::
  268. 'ignore' |
  269. {'ok', pid()} |
  270. {'ok', {pid(), reference()}} |
  271. {'error', term()}.
  272. -spec start(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  273. start(Module, Args, Opts) ->
  274. gen:start(?MODULE, nolink, Module, Args, Opts).
  275. -spec start(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  276. start(ServerName, Module, Args, Opts) ->
  277. gen:start(?MODULE, nolink, ServerName, Module, Args, Opts).
  278. -spec start_link(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  279. start_link(Module, Args, Opts) ->
  280. gen:start(?MODULE, link, Module, Args, Opts).
  281. -spec start_link(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  282. start_link(ServerName, Module, Args, Opts) ->
  283. gen:start(?MODULE, link, ServerName, Module, Args, Opts).
  284. %% Start and monitor
  285. -spec start_monitor(Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  286. start_monitor(Module, Args, Opts) ->
  287. gen:start(?MODULE, monitor, Module, Args, Opts).
  288. -spec start_monitor(ServerName :: serverName(), Module :: module(), Args :: term(), Opts :: [startOpt()]) -> startRet().
  289. start_monitor(ServerName, Module, Args, Opts) ->
  290. gen:start(?MODULE, monitor, ServerName, Module, Args, Opts).
  291. -spec stop(ServerRef :: serverRef()) -> ok.
  292. stop(ServerRef) ->
  293. gen:stop(ServerRef).
  294. -spec stop(ServerRef :: serverRef(), Reason :: term(), Timeout :: timeout()) -> ok.
  295. stop(ServerRef, Reason, Timeout) ->
  296. gen:stop(ServerRef, Reason, Timeout).
  297. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start stop API end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  298. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  299. doModuleInit(Module, Args) ->
  300. try
  301. Module:init(Args)
  302. catch
  303. throw:Ret -> Ret;
  304. Class:Reason:Stacktrace -> {'EXIT', Class, Reason, Stacktrace}
  305. end.
  306. init_it(Starter, self, ServerRef, Module, Args, Opts) ->
  307. init_it(Starter, self(), ServerRef, Module, Args, Opts);
  308. init_it(Starter, Parent, ServerRef, Module, Args, Opts) ->
  309. Name = gen:name(ServerRef),
  310. Debug = gen:debug_options(Name, Opts),
  311. HibernateAfterTimeout = gen:hibernate_after(Opts),
  312. case doModuleInit(Module, Args) of
  313. {ok, State} ->
  314. proc_lib:init_ack(Starter, {ok, self()}),
  315. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, undefined, State, []);
  316. {ok, Status, State} ->
  317. proc_lib:init_ack(Starter, {ok, self()}),
  318. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, []);
  319. {ok, Status, State, Actions} ->
  320. proc_lib:init_ack(Starter, {ok, self()}),
  321. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, listify(Actions));
  322. {stop, Reason} ->
  323. gen:unregister_name(ServerRef),
  324. proc_lib:init_ack(Starter, {error, Reason}),
  325. exit(Reason);
  326. ignore ->
  327. gen:unregister_name(ServerRef),
  328. proc_lib:init_ack(Starter, ignore),
  329. exit(normal);
  330. {'EXIT', Class, Reason, Stacktrace} ->
  331. gen:unregister_name(ServerRef),
  332. proc_lib:init_ack(Starter, {error, Reason}),
  333. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, fasle, #{}, [], #{}, '$un_init', '$un_init', Debug, []),
  334. erlang:raise(Class, Reason, Stacktrace);
  335. _Ret ->
  336. gen:unregister_name(ServerRef),
  337. Error = {'init_bad_return', _Ret},
  338. proc_lib:init_ack(Starter, {error, Error}),
  339. error_info(error, Error, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, fasle, #{}, [], #{}, '$un_init', '$un_init', Debug, []),
  340. exit(Error)
  341. end.
  342. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  343. %% 进入循环 调用该进程必须使用proc_lib启动 且已经初始化状态和数据 包括注册名称
  344. %% 可以通过使用与从init / 1返回的参数相同的参数,而不是通过start / 3,4或start_link / 3,4启动状态机,而将当前由proc_lib启动的进程转换为状态机。
  345. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()]) -> no_return().
  346. enter_loop(Module, Status, State, Opts) ->
  347. enter_loop(Module, Status, State, Opts, self(), []).
  348. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()], ServerOrActions :: serverName() | pid() | actions(eventAction())) -> no_return().
  349. enter_loop(Module, Status, State, Opts, ServerOrActions) ->
  350. if
  351. is_list(ServerOrActions) ->
  352. enter_loop(Module, Status, State, Opts, self(), ServerOrActions);
  353. true ->
  354. enter_loop(Module, Status, State, Opts, ServerOrActions, [])
  355. end.
  356. -spec enter_loop(Module :: module(), Status :: term(), State :: term(), Opts :: [enterLoopOpt()], Server :: serverName() | pid(), Actions :: actions(eventAction())) -> no_return().
  357. enter_loop(Module, Status, State, Opts, ServerName, Actions) ->
  358. is_atom(Module) orelse error({atom, Module}),
  359. Parent = gen:get_parent(),
  360. Name = gen:get_proc_name(ServerName),
  361. Debug = gen:debug_options(Name, Opts),
  362. HibernateAfterTimeout = gen:hibernate_after(Opts),
  363. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, Status, State, Actions).
  364. %% 这里的 init_it/6 和 enter_loop/5,6,7 函数汇聚
  365. loopEntry(Parent, Debug, Module, Name, HibernateAfterTimeout, CurStatus, CurState, Actions) ->
  366. %% 如果该进程用于 gen_event 或者该进程需要捕捉退出信号 和 捕捉supervisor进程树的退出信息 则需要设置 process_flag(trap_exit, true) 需要在Actions返回 {trap_exit, true}
  367. MewActions =
  368. case lists:keyfind(trap_exit, 1, Actions) of
  369. false ->
  370. Actions;
  371. {trap_exit, true} ->
  372. process_flag(trap_exit, true),
  373. lists:keydelete(trap_exit, 1, Actions);
  374. _ ->
  375. lists:keydelete(trap_exit, 1, Actions)
  376. end,
  377. NewDebug = ?SYS_DEBUG(Debug, Name, {enter, CurStatus}),
  378. %% 强制执行{postpone,false}以确保我们的假事件被丢弃
  379. LastActions = MewActions ++ [{isPos, false}],
  380. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, false, #{}, [], #{}, CurStatus, CurState, CurStatus, NewDebug, [{onevent, init_status}], true, LastActions, ?CB_FORM_EVENT).
  381. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  382. system_continue(Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}) ->
  383. if
  384. IsHib ->
  385. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib]);
  386. true ->
  387. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  388. end.
  389. system_terminate(Reason, Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, _IsHib}) ->
  390. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []).
  391. system_code_change({Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}, _Mod, OldVsn, Extra) ->
  392. case
  393. try Module:code_change(OldVsn, CurStatus, CurState, Extra)
  394. catch
  395. throw:Result -> Result;
  396. _C:_R:_S -> {_C, _R, _S}
  397. end
  398. of
  399. {ok, NewStatus, NewState} ->
  400. {ok, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, NewState, IsHib}};
  401. Error ->
  402. Error
  403. end.
  404. system_get_state({_Parent, _Name, _Module, _HibernateAfterTimeout, _IsEnter, _EpmHers, _Postponed, _Timers, CurStatus, CurState, _IsHib}) ->
  405. {ok, {CurStatus, CurState}}.
  406. system_replace_state(StatusFun, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}) ->
  407. {NewStatus, NewState} = StatusFun(CurStatus, CurState),
  408. {ok, {NewStatus, NewState}, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, NewState, IsHib}}.
  409. format_status(Opt, [PDict, SysStatus, Parent, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, _IsHib}]) ->
  410. Header = gen:format_status_header("Status for gen_ipc", Name),
  411. Log = sys:get_log(Debug),
  412. [
  413. {header, Header},
  414. {data,
  415. [
  416. {"Status", SysStatus},
  417. {"Parent", Parent},
  418. {"Time-outs", listTimeouts(Timers)},
  419. {"Logged Events", Log},
  420. {"Postponed", Postponed}
  421. ]
  422. } |
  423. case format_status(Opt, PDict, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState) of
  424. L when is_list(L) -> L;
  425. T -> [T]
  426. end
  427. ].
  428. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sys callbacks end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  429. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  430. -spec call(ServerRef :: serverRef(), Request :: term()) -> Reply :: term().
  431. call(ServerRef, Request) ->
  432. try gcall(ServerRef, '$gen_call', Request) of
  433. {ok, Reply} ->
  434. Reply
  435. catch Class:Reason ->
  436. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE())
  437. end.
  438. -spec call(ServerRef :: serverRef(), Request :: term(), Timeout :: timeout()) -> Reply :: term().
  439. call(ServerRef, Request, Timeout) ->
  440. try gcall(ServerRef, '$gen_call', Request, Timeout) of
  441. {ok, Reply} ->
  442. Reply
  443. catch Class:Reason ->
  444. erlang:raise(Class, {Reason, {?MODULE, call, [ServerRef, Request]}}, ?STACKTRACE())
  445. end.
  446. multi_call(Name, Request) when is_atom(Name) ->
  447. do_multi_call([node() | nodes()], Name, Request, infinity).
  448. multi_call(Nodes, Name, Request) when is_list(Nodes), is_atom(Name) ->
  449. do_multi_call(Nodes, Name, Request, infinity).
  450. multi_call(Nodes, Name, Request, infinity) ->
  451. do_multi_call(Nodes, Name, Request, infinity);
  452. multi_call(Nodes, Name, Request, Timeout) when is_list(Nodes), is_atom(Name), is_integer(Timeout), Timeout >= 0 ->
  453. do_multi_call(Nodes, Name, Request, Timeout).
  454. do_multi_call([Node], Name, Req, infinity) when Node =:= node() ->
  455. % Special case when multi_call is used with local node only.
  456. % In that case we can leverage the benefit of recv_mark optimisation
  457. % existing in simple gcall.
  458. try gcall(Name, '$gen_call', Req, infinity) of
  459. {ok, Res} -> {[{Node, Res}], []}
  460. catch exit:_ ->
  461. {[], [Node]}
  462. end;
  463. do_multi_call(Nodes, Name, Request, infinity) ->
  464. Tag = make_ref(),
  465. Monitors = send_nodes(Nodes, Name, Tag, Request),
  466. rec_nodes(Tag, Monitors, Name, undefined);
  467. do_multi_call(Nodes, Name, Request, Timeout) ->
  468. Tag = make_ref(),
  469. Caller = self(),
  470. Receiver = spawn(
  471. fun() ->
  472. process_flag(trap_exit, true),
  473. Mref = erlang:monitor(process, Caller),
  474. receive
  475. {Caller, Tag} ->
  476. Monitors = send_nodes(Nodes, Name, Tag, Request),
  477. TimerId = erlang:start_timer(Timeout, self(), ok),
  478. Result = rec_nodes(Tag, Monitors, Name, TimerId),
  479. exit({self(), Tag, Result});
  480. {'DOWN', Mref, _, _, _} ->
  481. exit(normal)
  482. end
  483. end
  484. ),
  485. Mref = erlang:monitor(process, Receiver),
  486. Receiver ! {self(), Tag},
  487. receive
  488. {'DOWN', Mref, _, _, {Receiver, Tag, Result}} ->
  489. Result;
  490. {'DOWN', Mref, _, _, Reason} ->
  491. exit(Reason)
  492. end.
  493. -spec cast(ServerRef :: serverRef(), Msg :: term()) -> ok.
  494. cast({global, Name}, Msg) ->
  495. try global:send(Name, {'$gen_cast', Msg}),
  496. ok
  497. catch _:_ -> ok
  498. end;
  499. cast({via, RegMod, Name}, Msg) ->
  500. try RegMod:send(Name, {'$gen_cast', Msg}),
  501. ok
  502. catch _:_ -> ok
  503. end;
  504. cast({Name, Node} = Dest, Msg) when is_atom(Name), is_atom(Node) ->
  505. try erlang:send(Dest, {'$gen_cast', Msg}),
  506. ok
  507. catch _:_ -> ok
  508. end;
  509. cast(Dest, Msg) ->
  510. try erlang:send(Dest, {'$gen_cast', Msg}),
  511. ok
  512. catch _:_ -> ok
  513. end.
  514. -spec send(ServerRef :: serverRef(), Msg :: term()) -> ok.
  515. send({global, Name}, Msg) ->
  516. try global:send(Name, Msg),
  517. ok
  518. catch _:_ -> ok
  519. end;
  520. send({via, RegMod, Name}, Msg) ->
  521. try RegMod:send(Name, Msg),
  522. ok
  523. catch _:_ -> ok
  524. end;
  525. send({Name, Node} = Dest, Msg) when is_atom(Name), is_atom(Node) ->
  526. try erlang:send(Dest, Msg),
  527. ok
  528. catch _:_ -> ok
  529. end;
  530. send(Dest, Msg) ->
  531. try erlang:send(Dest, Msg),
  532. ok
  533. catch _:_ -> ok
  534. end.
  535. %% 异步广播,不返回任何内容,只是发送“ n”祈祷
  536. abcast(Name, Msg) when is_atom(Name) ->
  537. doAbcast([node() | nodes()], Name, Msg).
  538. abcast(Nodes, Name, Msg) when is_list(Nodes), is_atom(Name) ->
  539. doAbcast(Nodes, Name, Msg).
  540. doAbcast(Nodes, Name, Msg) ->
  541. [
  542. begin
  543. try erlang:send({Name, Node}, {'$gen_cast', Msg}),
  544. ok
  545. catch
  546. _:_ -> ok
  547. end
  548. end || Node <- Nodes
  549. ],
  550. ok.
  551. -spec send_request(ServerRef :: serverRef(), Request :: term()) -> RequestId :: requestId().
  552. send_request(Name, Request) ->
  553. gen:send_request(Name, '$gen_call', Request).
  554. %% gen_event send_request/3
  555. -spec send_request(ServerRef :: serverRef(), epmHandler(), term()) -> requestId().
  556. send_request(Name, Handler, Query) ->
  557. gen:send_request(Name, self(), {call, Handler, Query}).
  558. -spec wait_response(RequestId :: requestId()) -> {reply, Reply :: term()} | {error, {term(), serverRef()}}.
  559. wait_response(RequestId) ->
  560. gen:wait_response(RequestId, infinity).
  561. -spec wait_response(RequestId :: requestId(), timeout()) -> {reply, Reply :: term()} | 'timeout' | {error, {term(), serverRef()}}.
  562. wait_response(RequestId, Timeout) ->
  563. gen:wait_response(RequestId, Timeout).
  564. -spec receive_response(RequestId :: serverRef()) -> {reply, Reply :: term()} | {error, {term(), serverRef()}}.
  565. receive_response(RequestId) ->
  566. gen:receive_response(RequestId, infinity).
  567. -spec receive_response(RequestId :: requestId(), timeout()) -> {reply, Reply :: term()} | 'timeout' | {error, {term(), serverRef()}}.
  568. receive_response(RequestId, Timeout) ->
  569. gen:receive_response(RequestId, Timeout).
  570. -spec check_response(Msg :: term(), RequestId :: requestId()) ->
  571. {reply, Reply :: term()} | 'no_reply' | {error, {term(), serverRef()}}.
  572. check_response(Msg, RequestId) ->
  573. gen:check_response(Msg, RequestId).
  574. send_nodes(Nodes, Name, Tag, Request) ->
  575. [
  576. begin
  577. Monitor = start_monitor(Node, Name),
  578. try {Name, Node} ! {'$gen_call', {self(), {Tag, Node}}, Request},
  579. ok
  580. catch _:_ -> ok
  581. end,
  582. Monitor
  583. end || Node <- Nodes, is_atom(Node)
  584. ].
  585. rec_nodes(Tag, Nodes, Name, TimerId) ->
  586. rec_nodes(Tag, Nodes, Name, [], [], 2000, TimerId).
  587. rec_nodes(Tag, [{N, R} | Tail], Name, BadNodes, Replies, Time, TimerId) ->
  588. receive
  589. {'DOWN', R, _, _, _} ->
  590. rec_nodes(Tag, Tail, Name, [N | BadNodes], Replies, Time, TimerId);
  591. {{Tag, N}, Reply} ->
  592. erlang:demonitor(R, [flush]),
  593. rec_nodes(Tag, Tail, Name, BadNodes,
  594. [{N, Reply} | Replies], Time, TimerId);
  595. {timeout, TimerId, _} ->
  596. erlang:demonitor(R, [flush]),
  597. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  598. end;
  599. rec_nodes(Tag, [N | Tail], Name, BadNodes, Replies, Time, TimerId) ->
  600. receive
  601. {nodedown, N} ->
  602. monitor_node(N, false),
  603. rec_nodes(Tag, Tail, Name, [N | BadNodes], Replies, 2000, TimerId);
  604. {{Tag, N}, Reply} ->
  605. receive {nodedown, N} -> ok after 0 -> ok end,
  606. monitor_node(N, false),
  607. rec_nodes(Tag, Tail, Name, BadNodes,
  608. [{N, Reply} | Replies], 2000, TimerId);
  609. {timeout, TimerId, _} ->
  610. receive {nodedown, N} -> ok after 0 -> ok end,
  611. monitor_node(N, false),
  612. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  613. after Time ->
  614. case erpc:call(N, erlang, whereis, [Name]) of
  615. Pid when is_pid(Pid) ->
  616. rec_nodes(Tag, [N | Tail], Name, BadNodes,
  617. Replies, infinity, TimerId);
  618. _ ->
  619. receive {nodedown, N} -> ok after 0 -> ok end,
  620. monitor_node(N, false),
  621. rec_nodes(Tag, Tail, Name, [N | BadNodes],
  622. Replies, 2000, TimerId)
  623. end
  624. end;
  625. rec_nodes(_, [], _, BadNodes, Replies, _, TimerId) ->
  626. case catch erlang:cancel_timer(TimerId) of
  627. false ->
  628. receive
  629. {timeout, TimerId, _} -> ok
  630. after 0 ->
  631. ok
  632. end;
  633. _ ->
  634. ok
  635. end,
  636. {Replies, BadNodes}.
  637. rec_nodes_rest(Tag, [{N, R} | Tail], Name, BadNodes, Replies) ->
  638. receive
  639. {'DOWN', R, _, _, _} ->
  640. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies);
  641. {{Tag, N}, Reply} ->
  642. erlang:demonitor(R, [flush]),
  643. rec_nodes_rest(Tag, Tail, Name, BadNodes, [{N, Reply} | Replies])
  644. after 0 ->
  645. erlang:demonitor(R, [flush]),
  646. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  647. end;
  648. rec_nodes_rest(Tag, [N | Tail], Name, BadNodes, Replies) ->
  649. receive
  650. {nodedown, N} ->
  651. monitor_node(N, false),
  652. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies);
  653. {{Tag, N}, Reply} ->
  654. receive {nodedown, N} -> ok after 0 -> ok end,
  655. monitor_node(N, false),
  656. rec_nodes_rest(Tag, Tail, Name, BadNodes, [{N, Reply} | Replies])
  657. after 0 ->
  658. receive {nodedown, N} -> ok after 0 -> ok end,
  659. monitor_node(N, false),
  660. rec_nodes_rest(Tag, Tail, Name, [N | BadNodes], Replies)
  661. end;
  662. rec_nodes_rest(_Tag, [], _Name, BadNodes, Replies) ->
  663. {Replies, BadNodes}.
  664. start_monitor(Node, Name) when is_atom(Node), is_atom(Name) ->
  665. if node() =:= nonode@nohost, Node =/= nonode@nohost ->
  666. Ref = make_ref(),
  667. self() ! {'DOWN', Ref, process, {Name, Node}, noconnection},
  668. {Node, Ref};
  669. true ->
  670. case catch erlang:monitor(process, {Name, Node}) of
  671. {'EXIT', _} ->
  672. monitor_node(Node, true),
  673. Node;
  674. Ref when is_reference(Ref) ->
  675. {Node, Ref}
  676. end
  677. end.
  678. %% Reply from a status machine callback to whom awaits in call/2
  679. -spec reply([replyAction(), ...] | replyAction()) -> ok.
  680. reply({reply, {To, Tag}, Reply}) ->
  681. try To ! {Tag, Reply},
  682. ok
  683. catch _:_ ->
  684. ok
  685. end;
  686. reply(Replies) when is_list(Replies) ->
  687. [greply(From, Reply) || {reply, From, Reply} <- Replies],
  688. ok.
  689. -compile({inline, [reply/2]}).
  690. -spec reply(From :: from(), Reply :: term()) -> ok.
  691. reply(From, Reply) ->
  692. greply(From, Reply).
  693. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API helpers end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  694. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  695. epmRequest({global, Name}, Msg) ->
  696. try global:send(Name, Msg),
  697. ok
  698. catch _:_ -> ok
  699. end;
  700. epmRequest({via, RegMod, Name}, Msg) ->
  701. try RegMod:send(Name, Msg),
  702. ok
  703. catch _:_ -> ok
  704. end;
  705. epmRequest(EpmSrv, Cmd) ->
  706. EpmSrv ! Cmd,
  707. ok.
  708. -spec epm_info(serverRef(), epmHandler(), term()) -> term().
  709. epm_info(EpmSrv, EpmHandler, Msg) ->
  710. epmRequest(EpmSrv, {'$epm_info', EpmHandler, Msg}).
  711. -spec info_notify(serverRef(), term()) -> 'ok'.
  712. info_notify(EpmSrv, Event) ->
  713. epmRequest(EpmSrv, {'$epm_info', '$infoNotify', Event}).
  714. epmRpc(EpmSrv, Cmd) ->
  715. try gcall(EpmSrv, '$epm_call', Cmd, infinity) of
  716. {ok, Reply} ->
  717. Reply
  718. catch Class:Reason ->
  719. erlang:raise(Class, {Reason, {?MODULE, call, [EpmSrv, Cmd, infinity]}}, ?STACKTRACE())
  720. end.
  721. epmRpc(EpmSrv, Cmd, Timeout) ->
  722. try gcall(EpmSrv, '$epm_call', Cmd, Timeout) of
  723. {ok, Reply} ->
  724. Reply
  725. catch Class:Reason ->
  726. erlang:raise(Class, {Reason, {?MODULE, call, [EpmSrv, Cmd, Timeout]}}, ?STACKTRACE())
  727. end.
  728. -spec call_notify(serverRef(), term()) -> 'ok'.
  729. call_notify(EpmSrv, Event) ->
  730. epmRpc(EpmSrv, {'$syncNotify', Event}).
  731. -spec epm_call(serverRef(), epmHandler(), term()) -> term().
  732. epm_call(EpmSrv, EpmHandler, Query) ->
  733. epmRpc(EpmSrv, {'$epmCall', EpmHandler, Query}).
  734. -spec epm_call(serverRef(), epmHandler(), term(), timeout()) -> term().
  735. epm_call(EpmSrv, EpmHandler, Query, Timeout) ->
  736. epmRpc(EpmSrv, {'$epmCall', EpmHandler, Query}, Timeout).
  737. -spec add_epm(serverRef(), epmHandler(), term()) -> term().
  738. add_epm(EpmSrv, EpmHandler, Args) ->
  739. epmRpc(EpmSrv, {'$addEpm', EpmHandler, Args}).
  740. -spec add_sup_epm(serverRef(), epmHandler(), term()) -> term().
  741. add_sup_epm(EpmSrv, EpmHandler, Args) ->
  742. epmRpc(EpmSrv, {'$addSupEpm', EpmHandler, Args, self()}).
  743. -spec del_epm(serverRef(), epmHandler(), term()) -> term().
  744. del_epm(EpmSrv, EpmHandler, Args) ->
  745. epmRpc(EpmSrv, {'$delEpm', EpmHandler, Args}).
  746. -spec swap_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
  747. swap_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
  748. epmRpc(EpmSrv, {'$swapEpm', H1, A1, H2, A2}).
  749. -spec swap_sup_epm(serverRef(), {epmHandler(), term()}, {epmHandler(), term()}) -> 'ok' | {'error', term()}.
  750. swap_sup_epm(EpmSrv, {H1, A1}, {H2, A2}) ->
  751. epmRpc(EpmSrv, {'$swapSupEpm', H1, A1, H2, A2, self()}).
  752. -spec which_epm(serverRef()) -> [epmHandler()].
  753. which_epm(EpmSrv) ->
  754. epmRpc(EpmSrv, '$which_handlers').
  755. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  756. %% EPM inner fun
  757. addNewEpm(InitRet, EpmHers, Module, EpmId, EpmSup) ->
  758. case InitRet of
  759. {ok, State} ->
  760. EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
  761. {ok, EpmHers#{EpmId => EpmHer}, false};
  762. {ok, State, hibernate} ->
  763. EpmHer = #epmHer{epmId = EpmId, epmM = Module, epmS = State, epmSup = EpmSup},
  764. {ok, EpmHers#{EpmId => EpmHer}, true};
  765. Other ->
  766. {Other, EpmHers, false}
  767. end.
  768. doAddEpm(EpmHers, {Module, _SubId} = EpmId, Args, EpmSup) ->
  769. case EpmHers of
  770. #{EpmId := _EpmHer} ->
  771. {{error, existed}, EpmHers, false};
  772. _ ->
  773. try Module:init(Args) of
  774. Result ->
  775. addNewEpm(Result, EpmHers, Module, EpmId, EpmSup)
  776. catch
  777. throw:Ret ->
  778. addNewEpm(Ret, EpmHers, Module, EpmId, EpmSup);
  779. C:R:S ->
  780. {{error, {C, R, S}}, EpmHers, false}
  781. end
  782. end;
  783. doAddEpm(EpmHers, Module, Args, EpmSup) ->
  784. case EpmHers of
  785. #{Module := _EpmHer} ->
  786. {{error, existed}, EpmHers, false};
  787. _ ->
  788. try Module:init(Args) of
  789. Result ->
  790. addNewEpm(Result, EpmHers, Module, Module, EpmSup)
  791. catch
  792. throw:Ret ->
  793. addNewEpm(Ret, EpmHers, Module, Module, EpmSup);
  794. C:R:S ->
  795. {{error, {C, R, S}}, EpmHers, false}
  796. end
  797. end.
  798. doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup) ->
  799. case doAddEpm(EpmHers, EpmHandler, Args, EpmSup) of
  800. {ok, _, _} = Result ->
  801. link(EpmSup),
  802. Result;
  803. Ret ->
  804. Ret
  805. end.
  806. doSwapEpm(EpmHers, EpmId1, Args1, EpmMId, Args2) ->
  807. case EpmHers of
  808. #{EpmId1 := #epmHer{epmSup = EpmSup} = EpmHer} ->
  809. State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
  810. NewEpmHers = maps:remove(EpmId1, EpmHers),
  811. case EpmSup of
  812. false ->
  813. doAddEpm(NewEpmHers, EpmMId, {Args2, State2}, undefined);
  814. _ ->
  815. doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup)
  816. end;
  817. undefined ->
  818. doAddEpm(EpmHers, EpmMId, {Args2, undefined}, undefined)
  819. end.
  820. doSwapSupEpm(EpmHers, EpmId1, Args1, EpmMId, Args2, EpmSup) ->
  821. case EpmHers of
  822. #{EpmId1 := EpmHer} ->
  823. State2 = epmTerminate(EpmHer, Args1, swapped, {swapped, EpmMId, EpmSup}),
  824. NewEpmHers = maps:remove(EpmId1, EpmHers),
  825. doAddSupEpm(NewEpmHers, EpmMId, {Args2, State2}, EpmSup);
  826. undefined ->
  827. doAddSupEpm(EpmHers, EpmMId, {Args2, undefined}, EpmSup)
  828. end.
  829. doNotify(EpmHers, Func, Event, _Form) ->
  830. allNotify(iterator(EpmHers), Func, Event, false, EpmHers, false).
  831. allNotify(Iterator, Func, Event, From, TemEpmHers, IsHib) ->
  832. case next(Iterator) of
  833. {K, _V, NextIterator} ->
  834. {NewEpmHers, NewIsHib} = doEpmHandle(TemEpmHers, K, Func, Event, From),
  835. allNotify(NextIterator, Func, Event, From, NewEpmHers, IsHib orelse NewIsHib);
  836. _ ->
  837. {TemEpmHers, IsHib}
  838. end.
  839. doEpmHandle(EpmHers, EpmHandler, Func, Event, From) ->
  840. case EpmHers of
  841. #{EpmHandler := #epmHer{epmM = EpmM, epmS = EpmS} = EpmHer} ->
  842. try EpmM:Func(Event, EpmS) of
  843. Result ->
  844. handleEpmCR(Result, EpmHers, EpmHer, Event, From)
  845. catch
  846. throw:Ret ->
  847. handleEpmCR(Ret, EpmHers, EpmHer, Event, From);
  848. C:R:S ->
  849. epmTerminate(EpmHer, {error, {C, R, S}}, Event, crash),
  850. NewEpmHers = maps:remove(EpmHandler, EpmHers),
  851. {NewEpmHers, false}
  852. end;
  853. _ ->
  854. try_greply(From, {error, bad_module}),
  855. {EpmHers, false}
  856. end.
  857. doDelEpm(EpmHers, EpmHandler, Args) ->
  858. case EpmHers of
  859. #{EpmHandler := EpmHer} ->
  860. epmTerminate(EpmHer, Args, delete, normal),
  861. {ok, maps:remove(EpmHandler, EpmHers)};
  862. undefined ->
  863. {{error, module_not_found}, EpmHers}
  864. end.
  865. epmTerminate(#epmHer{epmM = EpmM, epmS = State} = EpmHer, Args, LastIn, Reason) ->
  866. case erlang:function_exported(EpmM, terminate, 2) of
  867. true ->
  868. Res = (catch EpmM:terminate(Args, State)),
  869. reportTerminate(EpmHer, Reason, Args, LastIn, Res),
  870. Res;
  871. false ->
  872. reportTerminate(EpmHer, Reason, Args, LastIn, ok),
  873. ok
  874. end.
  875. reportTerminate(EpmHer, crash, {error, Why}, LastIn, _) ->
  876. reportTerminate2(EpmHer, Why, LastIn);
  877. %% How == normal | shutdown | {swapped, NewHandler, NewSupervisor}
  878. reportTerminate(EpmHer, How, _, LastIn, _) ->
  879. reportTerminate2(EpmHer, How, LastIn).
  880. reportTerminate2(#epmHer{epmSup = EpmSup, epmId = EpmId, epmS = State} = EpmHer, Reason, LastIn) ->
  881. report_error(EpmHer, Reason, State, LastIn),
  882. case EpmSup of
  883. undefined ->
  884. ok;
  885. _ ->
  886. EpmSup ! {gen_event_EXIT, EpmId, Reason},
  887. ok
  888. end.
  889. report_error(_EpmHer, normal, _, _) -> ok;
  890. report_error(_EpmHer, shutdown, _, _) -> ok;
  891. report_error(_EpmHer, {swapped, _, _}, _, _) -> ok;
  892. report_error(#epmHer{epmId = EpmId, epmM = EpmM}, Reason, State, LastIn) ->
  893. ?LOG_ERROR(
  894. #{
  895. label => {gen_ipc, epm_terminate},
  896. handler => {EpmId, EpmM},
  897. name => undefined,
  898. last_message => LastIn,
  899. state => State,
  900. reason => Reason
  901. },
  902. #{
  903. domain => [otp],
  904. report_cb => fun gen_ipc:epm_log/1,
  905. error_logger => #{tag => error}
  906. }).
  907. epm_log(#{label := {gen_ipc, epm_terminate}, handler := Handler, name := SName, last_message := LastIn, state := State, reason := Reason}) ->
  908. Reason1 =
  909. case Reason of
  910. {'EXIT', {undef, [{M, F, A, L} | MFAs]}} ->
  911. case code:is_loaded(M) of
  912. false ->
  913. {'module could not be loaded', [{M, F, A, L} | MFAs]};
  914. _ ->
  915. case erlang:function_exported(M, F, length(A)) of
  916. true ->
  917. {undef, [{M, F, A, L} | MFAs]};
  918. false ->
  919. {'function not exported', [{M, F, A, L} | MFAs]}
  920. end
  921. end;
  922. {'EXIT', Why} ->
  923. Why;
  924. _ ->
  925. Reason
  926. end,
  927. {"** gen_ipc emp handler ~p crashed.~n"
  928. "** Was installed in ~tp~n"
  929. "** Last event was: ~tp~n"
  930. "** When handler state == ~tp~n"
  931. "** Reason == ~tp~n", [Handler, SName, LastIn, State, Reason1]};
  932. epm_log(#{label := {gen_ipc, no_handle_info}, module := Module, message := Msg}) ->
  933. {"** Undefined handle_info in ~tp~n"
  934. "** Unhandled message: ~tp~n", [Module, Msg]}.
  935. epmStopAll(EpmHers) ->
  936. allStop(iterator(EpmHers)).
  937. allStop(Iterator) ->
  938. case next(Iterator) of
  939. {_K, V, NextIterator} ->
  940. epmTerminate(V, stop, 'receive', shutdown),
  941. case element(#epmHer.epmSup, V) of
  942. undefined ->
  943. ignore;
  944. EpmSup ->
  945. unlink(EpmSup)
  946. end,
  947. allStop(NextIterator);
  948. none ->
  949. ok
  950. end.
  951. epmStopOne(ExitEmpSup, EpmHers) ->
  952. forStopOne(iterator(EpmHers), ExitEmpSup, EpmHers).
  953. forStopOne(Iterator, ExitEmpSup, TemEpmHers) ->
  954. case next(Iterator) of
  955. {K, V, NextIterator} ->
  956. case element(#epmHer.epmSup, V) =:= ExitEmpSup of
  957. true ->
  958. epmTerminate(V, stop, 'receive', shutdown),
  959. forStopOne(NextIterator, ExitEmpSup, maps:remove(K, TemEpmHers));
  960. _ ->
  961. forStopOne(NextIterator, ExitEmpSup, TemEpmHers)
  962. end;
  963. none ->
  964. TemEpmHers
  965. end.
  966. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% gen_event end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  967. listify(Item) when is_list(Item) ->
  968. Item;
  969. listify(Item) ->
  970. [Item].
  971. %%%==========================================================================
  972. %%% Internal callbacks
  973. wakeupFromHib(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  974. %% 这是一条新消息,唤醒了我们,因此我们必须立即收到它
  975. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib).
  976. %%%==========================================================================
  977. %% Entry point for system_continue/3
  978. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  979. if
  980. IsHib ->
  981. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib]);
  982. true ->
  983. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  984. end.
  985. %% 接收新的消息
  986. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib) ->
  987. receive
  988. Msg ->
  989. case Msg of
  990. {'$gen_call', From, Request} ->
  991. matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request);
  992. {'$gen_cast', Cast} ->
  993. matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Cast);
  994. {timeout, TimerRef, TimeoutType} ->
  995. case Timers of
  996. #{TimeoutType := {TimerRef, TimeoutMsg}} ->
  997. NewTimers = maps:remove(TimeoutType, Timers),
  998. matchTimeoutMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, Debug, TimeoutType, TimeoutMsg);
  999. _ ->
  1000. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1001. end;
  1002. {system, PidFrom, Request} ->
  1003. %% 不返回但尾递归调用 system_continue/3
  1004. sys:handle_system_msg(Request, PidFrom, Parent, ?MODULE, Debug, {Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, IsHib}, IsHib);
  1005. {'EXIT', PidFrom, Reason} ->
  1006. case Parent =:= PidFrom of
  1007. true ->
  1008. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []);
  1009. _ ->
  1010. NewEpmHers = epmStopOne(PidFrom, EpmHers),
  1011. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1012. end;
  1013. {'$epm_call', From, Request} ->
  1014. matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request);
  1015. {'$epm_info', CmdOrEmpHandler, Event} ->
  1016. matchEpmInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CmdOrEmpHandler, Event);
  1017. _ ->
  1018. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg)
  1019. end
  1020. after
  1021. HibernateAfterTimeout ->
  1022. proc_lib:hibernate(?MODULE, wakeupFromHib, [Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib])
  1023. end.
  1024. matchCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request) ->
  1025. CurEvent = {{call, From}, Request},
  1026. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1027. try Module:handleCall(Request, CurStatus, CurState, From) of
  1028. Result ->
  1029. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, From)
  1030. catch
  1031. throw:Result ->
  1032. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, From);
  1033. Class:Reason:Strace ->
  1034. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1035. end.
  1036. matchCastMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Cast) ->
  1037. CurEvent = {cast, Cast},
  1038. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1039. try Module:handleCast(Cast, CurStatus, CurState) of
  1040. Result ->
  1041. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1042. catch
  1043. throw:Result ->
  1044. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1045. Class:Reason:Strace ->
  1046. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1047. end.
  1048. matchInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, Msg) ->
  1049. CurEvent = {info, Msg},
  1050. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1051. try Module:handleInfo(Msg, CurStatus, CurState) of
  1052. Result ->
  1053. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1054. catch
  1055. throw:Result ->
  1056. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1057. Class:Reason:Strace ->
  1058. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1059. end.
  1060. matchTimeoutMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, TimeoutType, TimeoutMsg) ->
  1061. CurEvent = {TimeoutType, TimeoutMsg},
  1062. NewDebug = ?SYS_DEBUG(Debug, Name, {in, CurEvent, CurStatus}),
  1063. try Module:handleOnevent(TimeoutType, TimeoutMsg, CurStatus, CurState) of
  1064. Result ->
  1065. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false)
  1066. catch
  1067. throw:Result ->
  1068. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent], Result, ?CB_FORM_EVENT, false);
  1069. Class:Reason:Strace ->
  1070. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [CurEvent])
  1071. end.
  1072. matchEpmCallMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, From, Request) ->
  1073. NewDebug = ?SYS_DEBUG(Debug, Name, {in, Request, CurStatus}),
  1074. case Request of
  1075. '$which_handlers' ->
  1076. reply(From, EpmHers);
  1077. {'$addEpm', EpmHandler, Args} ->
  1078. {Reply, NewEpmHers, IsHib} = doAddEpm(EpmHers, EpmHandler, Args, undefined),
  1079. reply(From, Reply),
  1080. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1081. {'$addSupEpm', EpmHandler, Args, EpmSup} ->
  1082. {Reply, NewEpmHers, IsHib} = doAddSupEpm(EpmHers, EpmHandler, Args, EpmSup),
  1083. reply(From, Reply),
  1084. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1085. {'$delEpm', EpmHandler, Args} ->
  1086. {Reply, NewEpmHers} = doDelEpm(EpmHers, EpmHandler, Args),
  1087. reply(From, Reply),
  1088. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, false);
  1089. {'$swapEpm', EpmId1, Args1, EpmId2, Args2} ->
  1090. {Reply, NewEpmHers, IsHib} = doSwapEpm(EpmHers, EpmId1, Args1, EpmId2, Args2),
  1091. reply(From, Reply),
  1092. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1093. {'$swapSupEpm', EpmId1, Args1, EpmId2, Args2, SupPid} ->
  1094. {Reply, NewEpmHers, IsHib} = doSwapSupEpm(EpmHers, EpmId1, Args1, EpmId2, Args2, SupPid),
  1095. reply(From, Reply),
  1096. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, IsHib);
  1097. {'$syncNotify', Event} ->
  1098. {NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
  1099. reply(From, ok),
  1100. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Request, IsHib);
  1101. {'$epmCall', EpmHandler, Query} ->
  1102. {NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleCall, Query, From),
  1103. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmCall, Request, IsHib)
  1104. end.
  1105. matchEpmInfoMsg(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CmdOrEmpHandler, Event) ->
  1106. NewDebug = ?SYS_DEBUG(Debug, Name, {in, {CmdOrEmpHandler, Event}, CurStatus}),
  1107. case CmdOrEmpHandler of
  1108. '$infoNotify' ->
  1109. {NewEpmHers, IsHib} = doNotify(EpmHers, handleEvent, Event, false),
  1110. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmEvent, Event, IsHib);
  1111. EpmHandler ->
  1112. {NewEpmHers, IsHib} = doEpmHandle(EpmHers, EpmHandler, handleInfo, Event, false),
  1113. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, NewEpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, handleEpmInfo, Event, IsHib)
  1114. end.
  1115. startEpmCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, CallbackFun, Event, IsHib) ->
  1116. case erlang:function_exported(Module, CallbackFun, 3) of
  1117. true ->
  1118. NewDebug = ?SYS_DEBUG(Debug, Name, {in, Event, CurStatus}),
  1119. try Module:CallbackFun(Event, CurStatus, CurState) of
  1120. Result ->
  1121. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event], Result, ?CB_FORM_EVENT, false)
  1122. catch
  1123. throw:Ret ->
  1124. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event], Ret, ?CB_FORM_EVENT, false);
  1125. Class:Reason:Strace ->
  1126. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, [Event])
  1127. end;
  1128. _ ->
  1129. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib)
  1130. end.
  1131. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter) ->
  1132. try Module:handleEnter(PrevStatus, CurStatus, CurState) of
  1133. Result ->
  1134. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result)
  1135. catch
  1136. throw:Result ->
  1137. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result);
  1138. Class:Reason:Strace ->
  1139. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1140. end.
  1141. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Args) ->
  1142. try Module:handleAfter(Args, CurStatus, CurState) of
  1143. Result ->
  1144. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_AFTER, false)
  1145. catch
  1146. throw:Result ->
  1147. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_AFTER, false);
  1148. Class:Reason:Strace ->
  1149. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1150. end.
  1151. startEventCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, {Type, Content}) ->
  1152. case Type of
  1153. 'cast' ->
  1154. try Module:handleCast(Content, CurStatus, CurState) of
  1155. Result ->
  1156. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1157. catch
  1158. throw:Ret ->
  1159. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1160. Class:Reason:Strace ->
  1161. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1162. end;
  1163. 'info' ->
  1164. try Module:handleInfo(Content, CurStatus, CurState) of
  1165. Result ->
  1166. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1167. catch
  1168. throw:Ret ->
  1169. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1170. Class:Reason:Strace ->
  1171. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1172. end;
  1173. {'call', From} ->
  1174. try Module:handleCall(Content, CurStatus, CurState, From) of
  1175. Result ->
  1176. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, From)
  1177. catch
  1178. throw:Ret ->
  1179. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, From);
  1180. Class:Reason:Strace ->
  1181. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1182. end;
  1183. _ ->
  1184. try Module:handleOnevent(Type, Content, CurStatus, CurState) of
  1185. Result ->
  1186. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, ?CB_FORM_EVENT, false)
  1187. catch
  1188. throw:Ret ->
  1189. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Ret, ?CB_FORM_EVENT, false);
  1190. Class:Reason:Strace ->
  1191. terminate(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1192. end
  1193. end.
  1194. %% handleEpmCallbackRet
  1195. handleEpmCR(Result, EpmHers, #epmHer{epmId = EpmId} = EpmHer, Event, From) ->
  1196. case Result of
  1197. kpS ->
  1198. {EpmHers, false};
  1199. {noreply, NewEpmS} ->
  1200. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1201. {EpmHers#{EpmId := MewEpmHer}, false};
  1202. {noreply, NewEpmS, hibernate} ->
  1203. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1204. {EpmHers#{EpmId := MewEpmHer}, true};
  1205. {swapEpm, NewEpmS, Args1, EpmMId, Args2} ->
  1206. #epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1207. State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
  1208. TemEpmHers = maps:remove(EpmId, EpmHers),
  1209. {_, NewEpmHers, IsHib} =
  1210. case EpmSup of
  1211. undefined ->
  1212. doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
  1213. _ ->
  1214. doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
  1215. end,
  1216. {NewEpmHers, IsHib};
  1217. {swapEpm, Reply, NewEpmS, Args1, EpmMId, Args2} ->
  1218. reply(From, Reply),
  1219. #epmHer{epmId = OldEpmMId, epmSup = EpmSup} = MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1220. State = epmTerminate(MewEpmHer, Args1, swapped, {swapped, OldEpmMId, EpmSup}),
  1221. TemEpmHers = maps:remove(EpmId, EpmHers),
  1222. {_, NewEpmHers, IsHib} =
  1223. case EpmSup of
  1224. undefined ->
  1225. doAddEpm(TemEpmHers, EpmMId, {Args2, State}, undefined);
  1226. _ ->
  1227. doAddSupEpm(TemEpmHers, EpmMId, {Args2, State}, EpmSup)
  1228. end,
  1229. {NewEpmHers, IsHib};
  1230. removeEpm ->
  1231. epmTerminate(EpmHer, removeEpm, remove, normal),
  1232. {maps:remove(EpmId, EpmHers), false};
  1233. {removeEpm, Reply} ->
  1234. reply(From, Reply),
  1235. epmTerminate(EpmHer, removeEpm, remove, normal),
  1236. {maps:remove(EpmId, EpmHers), false};
  1237. {reply, Reply} ->
  1238. reply(From, Reply),
  1239. {EpmHers, false};
  1240. {reply, Reply, NewEpmS} ->
  1241. reply(From, Reply),
  1242. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1243. {EpmHers#{EpmId := MewEpmHer}, false};
  1244. {reply, Reply, NewEpmS, hibernate} ->
  1245. reply(From, Reply),
  1246. MewEpmHer = setelement(#epmHer.epmS, EpmHer, NewEpmS),
  1247. {EpmHers#{EpmId := MewEpmHer}, true};
  1248. Other ->
  1249. epmTerminate(EpmHer, {error, Other}, Event, crash),
  1250. {maps:remove(EpmId, EpmHers), false}
  1251. end.
  1252. %% handleEnterCallbackRet
  1253. handleEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, Result) ->
  1254. case Result of
  1255. {kpS, NewState} ->
  1256. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false);
  1257. {kpS, NewState, Actions} ->
  1258. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false, listify(Actions));
  1259. kpS_S ->
  1260. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false);
  1261. {kpS_S, Actions} ->
  1262. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, false, listify(Actions));
  1263. {reS, NewState} ->
  1264. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true);
  1265. {reS, NewState, Actions} ->
  1266. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, NewState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true, listify(Actions));
  1267. reS_S ->
  1268. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true);
  1269. {reS_S, Actions} ->
  1270. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, PrevStatus, CurState, CurStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, true, listify(Actions));
  1271. stop ->
  1272. terminate(exit, normal, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1273. {stop, Reason} ->
  1274. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1275. {stop, Reason, NewState} ->
  1276. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, LeftEvents);
  1277. {stopReply, Reason, Replies} ->
  1278. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1279. try
  1280. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, LeftEvents)
  1281. after
  1282. case Replies of
  1283. {reply, RFrom, Reply} ->
  1284. reply(RFrom, Reply);
  1285. _ ->
  1286. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1287. ok
  1288. end
  1289. end;
  1290. {stopReply, Reason, Replies, NewState} ->
  1291. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1292. try
  1293. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, LeftEvents)
  1294. after
  1295. case Replies of
  1296. {reply, RFrom, Reply} ->
  1297. reply(RFrom, Reply);
  1298. _ ->
  1299. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1300. ok
  1301. end
  1302. end;
  1303. _ ->
  1304. terminate(error, {bad_handleEnterCR, Result}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1305. end.
  1306. handleEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Result, CallbackForm, From) ->
  1307. case Result of
  1308. {noreply, NewState} ->
  1309. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, false);
  1310. {noreply, NewState, Option} ->
  1311. case Option of
  1312. hibernate ->
  1313. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, true);
  1314. {doAfter, Args} ->
  1315. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [], Args);
  1316. _Ret ->
  1317. terminate(error, {bad_noreply, _Ret}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [])
  1318. end;
  1319. {reply, Reply, NewState} ->
  1320. reply(From, Reply),
  1321. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1322. receiveIng(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, false);
  1323. {reply, Reply, NewState, Option} ->
  1324. reply(From, Reply),
  1325. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1326. case Option of
  1327. hibernate ->
  1328. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, true);
  1329. {doAfter, Args} ->
  1330. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, [], Args);
  1331. _Ret ->
  1332. terminate(error, {bad_reply, _Ret}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, [])
  1333. end;
  1334. {sreply, Reply, NewStatus, NewState} ->
  1335. reply(From, Reply),
  1336. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1337. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, NewDebug, LeftEvents, NewStatus =/= CurStatus);
  1338. {sreply, Reply, NewStatus, NewState, Actions} ->
  1339. reply(From, Reply),
  1340. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1341. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, NewDebug, LeftEvents, NewStatus =/= CurStatus, listify(Actions), CallbackForm);
  1342. {nextS, NewStatus, NewState} ->
  1343. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, Debug, LeftEvents, NewStatus =/= CurStatus);
  1344. {nextS, NewStatus, NewState, Actions} ->
  1345. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewStatus, Debug, LeftEvents, NewStatus =/= CurStatus, listify(Actions), CallbackForm);
  1346. {kpS, NewState} ->
  1347. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, false);
  1348. {kpS, NewState, Actions} ->
  1349. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, false, listify(Actions), CallbackForm);
  1350. kpS_S ->
  1351. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, false);
  1352. {kpS_S, Actions} ->
  1353. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, false, listify(Actions), CallbackForm);
  1354. {reS, NewState} ->
  1355. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, true);
  1356. {reS, NewState, Actions} ->
  1357. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, CurStatus, Debug, LeftEvents, true, listify(Actions), CallbackForm);
  1358. reS_S ->
  1359. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, true);
  1360. {reS_S, Actions} ->
  1361. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, CurStatus, Debug, LeftEvents, true, listify(Actions), CallbackForm);
  1362. stop ->
  1363. terminate(exit, normal, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1364. {stop, Reason} ->
  1365. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents);
  1366. {stop, Reason, NewState} ->
  1367. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, Debug, LeftEvents);
  1368. {stopReply, Reason, Replies} ->
  1369. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1370. try
  1371. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewDebug, LeftEvents)
  1372. after
  1373. case Replies of
  1374. {reply, RFrom, Reply} ->
  1375. reply(RFrom, Reply);
  1376. _ when is_list(Replies) ->
  1377. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1378. ok;
  1379. _ ->
  1380. _ = reply(From, Replies)
  1381. end
  1382. end;
  1383. {stopReply, Reason, Replies, NewState} ->
  1384. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Replies}),
  1385. try
  1386. terminate(exit, Reason, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, NewState, NewDebug, LeftEvents)
  1387. after
  1388. case Replies of
  1389. {reply, RFrom, Reply} ->
  1390. _ = reply(RFrom, Reply);
  1391. _ when is_list(Replies) ->
  1392. [reply(RFrom, Reply) || {reply, RFrom, Reply} <- Replies],
  1393. ok;
  1394. _ ->
  1395. _ = reply(From, Replies)
  1396. end
  1397. end;
  1398. _ ->
  1399. terminate(error, {bad_handleEventCR, Result}, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1400. end.
  1401. dealEnterCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter, IsCallEnter) ->
  1402. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1403. case IsEnter andalso IsCallEnter of
  1404. true ->
  1405. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter);
  1406. false ->
  1407. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter)
  1408. end.
  1409. %% dealEventCallbackRet
  1410. dealEventCR(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, IsCallEnter) ->
  1411. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1412. case IsEnter andalso IsCallEnter of
  1413. true ->
  1414. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false);
  1415. false ->
  1416. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false)
  1417. end.
  1418. %% 处理enter callback 动作列表
  1419. %% parseEnterActionsList
  1420. parseEnterAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsCallEnter, IsHib, DoAfter, Actions) ->
  1421. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1422. %% enter 调用不能改成状态 actions 不能返回 IsPos = true 但是可以取消之前的推迟 设置IsPos = false 不能设置 doafter 不能插入事件
  1423. case Actions of
  1424. [] ->
  1425. case IsEnter andalso IsCallEnter of
  1426. true ->
  1427. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter);
  1428. _ ->
  1429. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, NextEs, IsPos, IsHib, DoAfter)
  1430. end;
  1431. _ ->
  1432. case doParseAL(Actions, ?CB_FORM_ENTER, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs) of
  1433. {error, ErrorContent} ->
  1434. terminate(error, ErrorContent, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, Debug, LeftEvents);
  1435. {NewIsEnter, NNewTimers, NewDebug, NewIsPos, NewIsHib, DoAfter, NewNextEs} ->
  1436. case NewIsEnter andalso IsCallEnter of
  1437. true ->
  1438. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, NewIsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, DoAfter);
  1439. _ ->
  1440. performTransitions(Parent, Name, Module, HibernateAfterTimeout, NewIsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, DoAfter)
  1441. end
  1442. end
  1443. end.
  1444. %% 处理非 enter 或者after callback 返回的动作列表
  1445. %% parseEventActionsList
  1446. parseEventAL(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, LeftEvents, IsCallEnter, Actions, CallbackForm) ->
  1447. NewTimers = cancelESTimeout(CurStatus =:= NewStatus, Timers),
  1448. case Actions of
  1449. [] ->
  1450. case IsEnter andalso IsCallEnter of
  1451. true ->
  1452. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false);
  1453. _ ->
  1454. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NewTimers, CurStatus, CurState, NewStatus, Debug, LeftEvents, [], false, false, false)
  1455. end;
  1456. _ ->
  1457. case doParseAL(Actions, CallbackForm, Name, IsEnter, NewTimers, Debug, false, false, false, []) of
  1458. {error, ErrorContent} ->
  1459. terminate(error, ErrorContent, ?STACKTRACE(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, []);
  1460. {NewIsEnter, NNewTimers, NewDebug, NewIsPos, NewIsHib, MewDoAfter, NewNextEs} ->
  1461. case NewIsEnter andalso IsCallEnter of
  1462. true ->
  1463. startEnterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, MewDoAfter);
  1464. _ ->
  1465. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, NNewTimers, CurStatus, CurState, NewStatus, NewDebug, LeftEvents, NewNextEs, NewIsPos, NewIsHib, MewDoAfter)
  1466. end
  1467. end
  1468. end.
  1469. %% loopParseActionsList
  1470. doParseAL([], _CallbackForm, _Name, IsEnter, Times, Debug, IsPos, IsHib, DoAfter, NextEs) ->
  1471. {IsEnter, Times, Debug, IsPos, IsHib, DoAfter, NextEs};
  1472. doParseAL([OneAction | LeftActions], CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, DoAfter, NextEs) ->
  1473. case OneAction of
  1474. {reply, From, Reply} ->
  1475. reply(From, Reply),
  1476. NewDebug = ?SYS_DEBUG(Debug, Name, {out, Reply, From}),
  1477. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, NewDebug, IsPos, IsHib, DoAfter, NextEs);
  1478. {eTimeout, Time, TimeoutMsg} ->
  1479. case Time of
  1480. infinity ->
  1481. NewTimers = doCancelTimer(eTimeout, Timers),
  1482. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1483. _ ->
  1484. TimerRef = erlang:start_timer(Time, self(), eTimeout),
  1485. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {eTimeout, Time, TimeoutMsg, []}}),
  1486. NewTimers = doRegisterTimer(eTimeout, TimerRef, TimeoutMsg, Timers),
  1487. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1488. end;
  1489. {sTimeout, Time, TimeoutMsg} ->
  1490. case Time of
  1491. infinity ->
  1492. NewTimers = doCancelTimer(sTimeout, Timers),
  1493. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1494. _ ->
  1495. TimerRef = erlang:start_timer(Time, self(), sTimeout),
  1496. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {sTimeout, Time, TimeoutMsg, []}}),
  1497. NewTimers = doRegisterTimer(sTimeout, TimerRef, TimeoutMsg, Timers),
  1498. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1499. end;
  1500. {gTimeout, TimeoutName, Time, TimeoutMsg} ->
  1501. case Time of
  1502. infinity ->
  1503. NewTimers = doCancelTimer(TimeoutName, Timers),
  1504. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1505. _ ->
  1506. TimerRef = erlang:start_timer(Time, self(), TimeoutName),
  1507. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, []}}),
  1508. NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers),
  1509. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1510. end;
  1511. {eTimeout, Time, TimeoutMsg, Options} ->
  1512. case Time of
  1513. infinity ->
  1514. NewTimers = doCancelTimer(eTimeout, Timers),
  1515. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1516. _ ->
  1517. TimerRef = erlang:start_timer(Time, self(), eTimeout, Options),
  1518. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {eTimeout, Time, TimeoutMsg, Options}}),
  1519. NewTimers = doRegisterTimer(eTimeout, TimerRef, TimeoutMsg, Timers),
  1520. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1521. end;
  1522. {sTimeout, Time, TimeoutMsg, Options} ->
  1523. case Time of
  1524. infinity ->
  1525. NewTimers = doCancelTimer(sTimeout, Timers),
  1526. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1527. _ ->
  1528. TimerRef = erlang:start_timer(Time, self(), sTimeout, Options),
  1529. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {sTimeout, Time, TimeoutMsg, Options}}),
  1530. NewTimers = doRegisterTimer(sTimeout, TimerRef, TimeoutMsg, Timers),
  1531. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1532. end;
  1533. {gTimeout, TimeoutName, Time, TimeoutMsg, Options} ->
  1534. case Time of
  1535. infinity ->
  1536. NewTimers = doCancelTimer(TimeoutName, Timers),
  1537. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1538. _ ->
  1539. TimerRef = erlang:start_timer(Time, self(), TimeoutName, Options),
  1540. NewDebug = ?SYS_DEBUG(Debug, Name, {start_timer, {TimeoutName, Time, TimeoutMsg, Options}}),
  1541. NewTimers = doRegisterTimer(TimeoutName, TimerRef, TimeoutMsg, Timers),
  1542. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, NewDebug, IsPos, IsHib, DoAfter, NextEs)
  1543. end;
  1544. {u_eTimeout, NewTimeoutMsg} ->
  1545. NewTimers = doUpdateTimer(eTimeout, NewTimeoutMsg, Timers),
  1546. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1547. {u_sTimeout, NewTimeoutMsg} ->
  1548. NewTimers = doUpdateTimer(sTimeout, NewTimeoutMsg, Timers),
  1549. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1550. {u_gTimeout, TimeoutName, NewTimeoutMsg} ->
  1551. NewTimers = doUpdateTimer(TimeoutName, NewTimeoutMsg, Timers),
  1552. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1553. c_eTimeout ->
  1554. NewTimers = doCancelTimer(eTimeout, Timers),
  1555. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1556. c_sTimeout ->
  1557. NewTimers = doCancelTimer(sTimeout, Timers),
  1558. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1559. {c_gTimeout, TimeoutName} ->
  1560. NewTimers = doCancelTimer(TimeoutName, Timers),
  1561. doParseAL(LeftActions, CallbackForm, Name, IsEnter, NewTimers, Debug, IsPos, IsHib, DoAfter, NextEs);
  1562. {isEnter, NewIsEnter} ->
  1563. NewDebug = ?SYS_DEBUG(Debug, Name, {change_isEnter, NewIsEnter}),
  1564. doParseAL(LeftActions, CallbackForm, Name, Timers, NewIsEnter, NewDebug, IsPos, IsHib, DoAfter, NextEs);
  1565. {isHib, NewIsHib} ->
  1566. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, NewIsHib, DoAfter, NextEs);
  1567. {isPos, NewIsPos} when (not NewIsPos orelse CallbackForm == ?CB_FORM_EVENT) ->
  1568. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, NewIsPos, IsHib, DoAfter, NextEs);
  1569. {doAfter, Args} when CallbackForm == ?CB_FORM_EVENT ->
  1570. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, {true, Args}, NextEs);
  1571. {nextE, Type, Content} when CallbackForm == ?CB_FORM_EVENT orelse CallbackForm == ?CB_FORM_AFTER ->
  1572. %% 处理next_event动作
  1573. doParseAL(LeftActions, CallbackForm, Name, IsEnter, Timers, Debug, IsPos, IsHib, DoAfter, [{Type, Content} | NextEs]);
  1574. _ ->
  1575. {error, {bad_ActionType, OneAction}}
  1576. end.
  1577. % checkTimeOptions({TimeoutType, Time, TimeoutMsg, Options} = NewTV) ->
  1578. % case Options of
  1579. % [{abs, true}] when ?ABS_TIMEOUT(Time) ->
  1580. % NewTV;
  1581. % [{abs, false}] when ?REL_TIMEOUT(Time) ->
  1582. % {TimeoutType, Time, TimeoutMsg};
  1583. % [] when ?REL_TIMEOUT(Time) ->
  1584. % {TimeoutType, Time, TimeoutMsg};
  1585. % _ ->
  1586. % %% 如果将来 start_timer opt扩展了 这里的代码也要修改
  1587. % error_timeout_opt
  1588. % end.
  1589. %% 进行状态转换
  1590. performTransitions(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, NewStatus, Debug, AllLeftEvents, NextEs, IsPos, IsHib, DoAfter) ->
  1591. %% 已收集所有选项,并缓冲next_events。执行实际状态转换。如果推迟则将当前事件移至推迟
  1592. %% 此时 NextEs的顺序与最开始出现的顺序相反. 后面执行的顺序 当前新增事件 + 反序的Postpone事件 + LeftEvents
  1593. case AllLeftEvents of
  1594. [] ->
  1595. CurEvent = undefined,
  1596. LeftEvents = [];
  1597. _ ->
  1598. [CurEvent | LeftEvents] = AllLeftEvents
  1599. end,
  1600. NewDebug = ?SYS_DEBUG(Debug, Name, case IsPos of true -> {postpone, CurEvent, CurStatus, NewStatus}; _ -> {consume, CurEvent, CurStatus, NewStatus} end),
  1601. if
  1602. CurStatus =:= NewStatus ->
  1603. %% Cancel event timeout
  1604. if
  1605. IsPos ->
  1606. LastLeftEvents =
  1607. case NextEs of
  1608. [] ->
  1609. LeftEvents;
  1610. [Es1] ->
  1611. [Es1 | LeftEvents];
  1612. [Es2, Es1] ->
  1613. [Es1, Es2 | LeftEvents];
  1614. _ ->
  1615. lists:reverse(NextEs, LeftEvents)
  1616. end,
  1617. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [CurEvent | Postponed], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter);
  1618. true ->
  1619. LastLeftEvents =
  1620. case NextEs of
  1621. [] ->
  1622. LeftEvents;
  1623. [Es1] ->
  1624. [Es1 | LeftEvents];
  1625. [Es2, Es1] ->
  1626. [Es1, Es2 | LeftEvents];
  1627. _ ->
  1628. lists:reverse(NextEs, LeftEvents)
  1629. end,
  1630. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter)
  1631. end;
  1632. true ->
  1633. %% 状态发生改变 重试推迟的事件
  1634. if
  1635. IsPos ->
  1636. NewLeftEvents =
  1637. case Postponed of
  1638. [] ->
  1639. [CurEvent | LeftEvents];
  1640. [E1] ->
  1641. [E1, CurEvent | LeftEvents];
  1642. [E2, E1] ->
  1643. [E1, E2, CurEvent | LeftEvents];
  1644. _ ->
  1645. lists:reverse(Postponed, [CurEvent | LeftEvents])
  1646. end,
  1647. LastLeftEvents =
  1648. case NextEs of
  1649. [] ->
  1650. NewLeftEvents;
  1651. [Es1] ->
  1652. [Es1 | NewLeftEvents];
  1653. [Es2, Es1] ->
  1654. [Es1, Es2 | NewLeftEvents];
  1655. _ ->
  1656. lists:reverse(NextEs, NewLeftEvents)
  1657. end,
  1658. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter);
  1659. true ->
  1660. NewLeftEvents =
  1661. case Postponed of
  1662. [] ->
  1663. LeftEvents;
  1664. [E1] ->
  1665. [E1 | LeftEvents];
  1666. [E2, E1] ->
  1667. [E1, E2 | LeftEvents];
  1668. _ ->
  1669. lists:reverse(Postponed, LeftEvents)
  1670. end,
  1671. LastLeftEvents =
  1672. case NextEs of
  1673. [] ->
  1674. NewLeftEvents;
  1675. [Es1] ->
  1676. [Es1 | NewLeftEvents];
  1677. [Es2, Es1] ->
  1678. [Es1, Es2 | NewLeftEvents];
  1679. _ ->
  1680. lists:reverse(NextEs, NewLeftEvents)
  1681. end,
  1682. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, [], Timers, NewStatus, CurState, NewDebug, LastLeftEvents, IsHib, DoAfter)
  1683. end
  1684. end.
  1685. %% 状态转换已完成,如果有排队事件,则继续循环,否则获取新事件
  1686. performEvents(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, IsHib, DoAfter) ->
  1687. % io:format("loop_done: status_data = ~p ~n postponed = ~p LeftEvents = ~p ~n timers = ~p.~n", [S#status.status_data,,S#status.postponed,LeftEvents,S#status.timers]),
  1688. case DoAfter of
  1689. {true, Args} ->
  1690. %% 这里 IsHib设置会被丢弃 按照gen_server中的设计 continue 和 hiernate是互斥的
  1691. startAfterCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Args);
  1692. _ ->
  1693. case LeftEvents of
  1694. [] ->
  1695. reLoopEntry(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, IsHib);
  1696. [Event | _Events] ->
  1697. %% 循环直到没有排队事件
  1698. if
  1699. IsHib ->
  1700. %% _ = garbage_collect(),
  1701. erts_internal:garbage_collect(major);
  1702. true ->
  1703. ignore
  1704. end,
  1705. startEventCall(Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents, Event)
  1706. end
  1707. end.
  1708. %% 取消事件超时 和 状态超时
  1709. cancelESTimeout(true, Timers) ->
  1710. %% Cancel event timeout
  1711. case Timers of
  1712. #{eTimeout := {TimerRef, _TimeoutMsg}} ->
  1713. cancelTimer(eTimeout, TimerRef, Timers);
  1714. _ ->
  1715. Timers
  1716. end;
  1717. cancelESTimeout(false, Timers) ->
  1718. %% 取消 status and event timeout
  1719. case Timers of
  1720. #{sTimeout := {STimerRef, _STimeoutMsg}} ->
  1721. TemTimer = cancelTimer(sTimeout, STimerRef, Timers),
  1722. case TemTimer of
  1723. #{eTimeout := {ETimerRef, _ETimeoutMsg}} ->
  1724. cancelTimer(eTimeout, ETimerRef, TemTimer);
  1725. _ ->
  1726. TemTimer
  1727. end;
  1728. _ ->
  1729. case Timers of
  1730. #{eTimeout := {ETimerRef, _ETimeoutMsg}} ->
  1731. cancelTimer(eTimeout, ETimerRef, Timers);
  1732. _ ->
  1733. Timers
  1734. end
  1735. end.
  1736. doRegisterTimer(TimeoutType, NewTimerRef, TimeoutMsg, Timers) ->
  1737. case Timers of
  1738. #{TimeoutType := {OldTimerRef, _OldTimeMsg}} ->
  1739. justCancelTimer(TimeoutType, OldTimerRef),
  1740. Timers#{TimeoutType := {NewTimerRef, TimeoutMsg}};
  1741. _ ->
  1742. Timers#{TimeoutType => {NewTimerRef, TimeoutMsg}}
  1743. end.
  1744. doCancelTimer(TimeoutType, Timers) ->
  1745. case Timers of
  1746. #{TimeoutType := {TimerRef, _TimeoutMsg}} ->
  1747. cancelTimer(TimeoutType, TimerRef, Timers);
  1748. _ ->
  1749. Timers
  1750. end.
  1751. doUpdateTimer(TimeoutType, Timers, TimeoutMsg) ->
  1752. case Timers of
  1753. #{TimeoutType := {TimerRef, _OldTimeoutMsg}} ->
  1754. Timers#{TimeoutType := {TimerRef, TimeoutMsg}};
  1755. _ ->
  1756. Timers
  1757. end.
  1758. justCancelTimer(TimeoutType, TimerRef) ->
  1759. case erlang:cancel_timer(TimerRef) of
  1760. false ->
  1761. %% 找不到计时器,我们还没有看到超时消息
  1762. receive
  1763. {timeout, TimerRef, TimeoutType} ->
  1764. %% 丢弃该超时消息
  1765. ok
  1766. after 0 ->
  1767. ok
  1768. end;
  1769. _ ->
  1770. %% Timer 已经运行了
  1771. ok
  1772. end.
  1773. cancelTimer(TimeoutType, TimerRef, Timers) ->
  1774. case erlang:cancel_timer(TimerRef) of
  1775. false ->
  1776. %% 找不到计时器,我们还没有看到超时消息
  1777. receive
  1778. {timeout, TimerRef, TimeoutType} ->
  1779. %% 丢弃该超时消息
  1780. ok
  1781. after 0 ->
  1782. ok
  1783. end;
  1784. _ ->
  1785. %% Timer 已经运行了
  1786. ok
  1787. end,
  1788. maps:remove(TimeoutType, Timers).
  1789. %% 排队立即超时事件(超时0事件)
  1790. %% 自事件超时0起,事件得到特殊处理
  1791. %% 任何收到的事件都会取消事件超时,
  1792. %% 因此,如果在事件超时0事件之前存在入队事件-事件超时被取消,因此没有事件。
  1793. %% 其他(status_timeout和{timeout,Name})超时0个事件
  1794. %% 在事件计时器超时0事件之后发生的事件被认为是
  1795. %% 属于在事件计时器之后启动的计时器
  1796. %% 已触发超时0事件,因此它们不会取消事件计时器。
  1797. %% mergeTimeoutEvents([], _Status, _CycleData, Debug, Events) ->
  1798. %% {Events, Debug};
  1799. %% mergeTimeoutEvents([{eTimeout, _} = TimeoutEvent | TimeoutEvents], Status, CycleData, Debug, []) ->
  1800. %% %% 由于队列中没有其他事件,因此添加该事件零超时事件
  1801. %% NewDebug = ?SYS_DEBUG(Debug, CycleData, {insert_timeout, TimeoutEvent, Status}),
  1802. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, NewDebug, [TimeoutEvent]);
  1803. %% mergeTimeoutEvents([{eTimeout, _} | TimeoutEvents], Status, CycleData, Debug, Events) ->
  1804. %% %% 忽略,因为队列中还有其他事件,因此它们取消了事件超时0。
  1805. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, Debug, Events);
  1806. %% mergeTimeoutEvents([TimeoutEvent | TimeoutEvents], Status, CycleData, Debug, Events) ->
  1807. %% %% Just prepend all others
  1808. %% NewDebug = ?SYS_DEBUG(Debug, CycleData, {insert_timeout, TimeoutEvent, Status}),
  1809. %% mergeTimeoutEvents(TimeoutEvents, Status, CycleData, NewDebug, [TimeoutEvent | Events]).
  1810. %% Return a list of all pending timeouts
  1811. listTimeouts(Timers) ->
  1812. {maps:size(Timers), allTimer(iterator(Timers), [])}.
  1813. allTimer(Iterator, Acc) ->
  1814. case next(Iterator) of
  1815. {TimeoutType, {_TimerRef, TimeoutMsg}, NextIterator} ->
  1816. allTimer(NextIterator, [{TimeoutType, TimeoutMsg} | Acc]);
  1817. none ->
  1818. Acc
  1819. end.
  1820. %%---------------------------------------------------------------------------
  1821. terminate(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents) ->
  1822. epmStopAll(EpmHers),
  1823. %% 这里停止所有的epm 但是并没有更新 epmHers为#{} 目前感觉没必要清理掉
  1824. case erlang:function_exported(Module, terminate, 3) of
  1825. true ->
  1826. try Module:terminate(Reason, CurStatus, CurState) of
  1827. _ -> ok
  1828. catch
  1829. throw:_ -> ok;
  1830. Class:Reason:Strace ->
  1831. error_info(Class, Reason, Strace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents),
  1832. erlang:raise(Class, Reason, Strace)
  1833. end;
  1834. false ->
  1835. ok
  1836. end,
  1837. case Reason of
  1838. normal ->
  1839. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1840. shutdown ->
  1841. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1842. {shutdown, _} ->
  1843. ?SYS_DEBUG(Debug, Name, {terminate, Reason, CurStatus});
  1844. _ ->
  1845. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents)
  1846. end,
  1847. case Stacktrace of
  1848. [] ->
  1849. erlang:Class(Reason);
  1850. _ ->
  1851. erlang:raise(Class, Reason, Stacktrace)
  1852. end.
  1853. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% debug 日志 Start%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1854. error_info(Class, Reason, Stacktrace, Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState, Debug, LeftEvents) ->
  1855. Log = sys:get_log(Debug),
  1856. ?LOG_ERROR(
  1857. #{
  1858. label => {gen_ipc, terminate},
  1859. name => Name,
  1860. module => Module,
  1861. queue => LeftEvents,
  1862. postponed => Postponed,
  1863. isEnter => IsEnter,
  1864. status => format_status(terminate, get(), Parent, Name, Module, HibernateAfterTimeout, IsEnter, EpmHers, Postponed, Timers, CurStatus, CurState),
  1865. timeouts => listTimeouts(Timers),
  1866. log => Log,
  1867. reason => {Class, Reason, Stacktrace},
  1868. client_info => cliStacktrace(LeftEvents)
  1869. },
  1870. #{
  1871. domain => [otp],
  1872. report_cb => fun gen_ipc:format_log/2,
  1873. error_logger => #{tag => error, report_cb => fun gen_ipc:format_log/1}}).
  1874. cliStacktrace([]) ->
  1875. undefined;
  1876. cliStacktrace([{{call, {Pid, _Tag}}, _Req} | _]) when is_pid(Pid) ->
  1877. if
  1878. node(Pid) =:= node() ->
  1879. case process_info(Pid, [current_stacktrace, registered_name]) of
  1880. undefined ->
  1881. {Pid, dead};
  1882. [{current_stacktrace, Stacktrace}, {registered_name, []}] ->
  1883. {Pid, {Pid, Stacktrace}};
  1884. [{current_stacktrace, Stacktrace}, {registered_name, Name}] ->
  1885. {Pid, {Name, Stacktrace}}
  1886. end;
  1887. true ->
  1888. {Pid, remote}
  1889. end;
  1890. cliStacktrace([_ | _]) ->
  1891. undefined;
  1892. cliStacktrace(_) ->
  1893. undefined.
  1894. %% format_log/1 is the report callback used by Logger handler
  1895. %% error_logger only. It is kept for backwards compatibility with
  1896. %% legacy error_logger event handlers. This function must always
  1897. %% return {Format,Args} compatible with the arguments in this module's
  1898. %% calls to error_logger prior to OTP-21.0.
  1899. format_log(Report) ->
  1900. Depth = error_logger:get_format_depth(),
  1901. FormatOpts = #{
  1902. chars_limit => unlimited,
  1903. depth => Depth,
  1904. single_line => false,
  1905. encoding => utf8
  1906. },
  1907. format_log_multi(limit_report(Report, Depth), FormatOpts).
  1908. limit_report(Report, unlimited) ->
  1909. Report;
  1910. limit_report(
  1911. #{
  1912. label := {gen_ipc, terminate},
  1913. queue := Q,
  1914. postponed := Postponed,
  1915. module := Module,
  1916. status := FmtData,
  1917. timeouts := Timeouts,
  1918. log := Log,
  1919. reason := {Class, Reason, Stacktrace},
  1920. client_info := ClientInfo
  1921. } = Report,
  1922. Depth) ->
  1923. Report#{
  1924. queue =>
  1925. case Q of
  1926. [Event | Events] ->
  1927. [io_lib:limit_term(Event, Depth) | io_lib:limit_term(Events, Depth)];
  1928. _ ->
  1929. []
  1930. end,
  1931. postponed =>
  1932. case Postponed of
  1933. [] -> [];
  1934. _ -> io_lib:limit_term(Postponed, Depth)
  1935. end,
  1936. modules => io_lib:limit_term(Module, Depth),
  1937. status => io_lib:limit_term(FmtData, Depth),
  1938. timeouts =>
  1939. case Timeouts of
  1940. {0, _} -> Timeouts;
  1941. _ -> io_lib:limit_term(Timeouts, Depth)
  1942. end,
  1943. log =>
  1944. case Log of
  1945. [] -> [];
  1946. _ -> [io_lib:limit_term(T, Depth) || T <- Log]
  1947. end,
  1948. reason =>
  1949. {Class, io_lib:limit_term(Reason, Depth), io_lib:limit_term(Stacktrace, Depth)},
  1950. client_info => limit_client_info(ClientInfo, Depth)
  1951. }.
  1952. limit_client_info({Pid, {Name, Stacktrace}}, Depth) ->
  1953. {Pid, {Name, io_lib:limit_term(Stacktrace, Depth)}};
  1954. limit_client_info(Client, _Depth) ->
  1955. Client.
  1956. %% format_log/2 is the report callback for any Logger handler, except
  1957. %% error_logger.
  1958. format_log(Report, FormatOpts0) ->
  1959. Default = #{
  1960. chars_limit => unlimited,
  1961. depth => unlimited,
  1962. single_line => false,
  1963. encoding => utf8
  1964. },
  1965. FormatOpts = maps:merge(Default, FormatOpts0),
  1966. IoOpts =
  1967. case FormatOpts of
  1968. #{chars_limit := unlimited} -> [];
  1969. #{chars_limit := Limit} -> [{chars_limit, Limit}]
  1970. end,
  1971. {Format, Args} = format_log_single(Report, FormatOpts),
  1972. io_lib:format(Format, Args, IoOpts).
  1973. format_log_single(
  1974. #{
  1975. label := {gen_ipc, terminate},
  1976. name := Name,
  1977. queue := Q,
  1978. %% postponed
  1979. %% isEnter
  1980. status := FmtData,
  1981. %% timeouts
  1982. log := Log,
  1983. reason := {Class, Reason, Stacktrace},
  1984. client_info := ClientInfo
  1985. },
  1986. #{single_line := true, depth := Depth} = FormatOpts) ->
  1987. P = p(FormatOpts),
  1988. {FixedReason, FixedStacktrace} = fix_reason(Class, Reason, Stacktrace),
  1989. {ClientFmt, ClientArgs} = format_client_log_single(ClientInfo, P, Depth),
  1990. Format =
  1991. lists:append(
  1992. ["State machine ", P, " terminating. Reason: ", P,
  1993. case FixedStacktrace of
  1994. [] -> "";
  1995. _ -> ". Stack: " ++ P
  1996. end,
  1997. case Q of
  1998. [] -> "";
  1999. _ -> ". Last event: " ++ P
  2000. end,
  2001. ". State: ", P,
  2002. case Log of
  2003. [] -> "";
  2004. _ -> ". Log: " ++ P
  2005. end,
  2006. "."]
  2007. ),
  2008. Args0 =
  2009. [Name, FixedReason] ++
  2010. case FixedStacktrace of
  2011. [] -> [];
  2012. _ -> [FixedStacktrace]
  2013. end ++
  2014. case Q of
  2015. [] -> [];
  2016. [Event | _] -> [Event]
  2017. end ++
  2018. [FmtData] ++
  2019. case Log of
  2020. [] -> [];
  2021. _ -> [Log]
  2022. end,
  2023. Args =
  2024. case Depth of
  2025. unlimited ->
  2026. Args0;
  2027. _ ->
  2028. lists:flatmap(fun(A) -> [A, Depth] end, Args0)
  2029. end,
  2030. {Format ++ ClientFmt, Args ++ ClientArgs};
  2031. format_log_single(Report, FormatOpts) ->
  2032. format_log_multi(Report, FormatOpts).
  2033. format_log_multi(
  2034. #{
  2035. label := {gen_ipc, terminate},
  2036. name := Name,
  2037. queue := Q,
  2038. postponed := Postponed,
  2039. module := Module,
  2040. isEnter := StateEnter,
  2041. status := FmtData,
  2042. timeouts := Timeouts,
  2043. log := Log,
  2044. reason := {Class, Reason, Stacktrace},
  2045. client_info := ClientInfo
  2046. },
  2047. #{depth := Depth} = FormatOpts) ->
  2048. P = p(FormatOpts),
  2049. {FixedReason, FixedStacktrace} = fix_reason(Class, Reason, Stacktrace),
  2050. {ClientFmt, ClientArgs} = format_client_log(ClientInfo, P, Depth),
  2051. CBMode =
  2052. case StateEnter of
  2053. true ->
  2054. [Module, 'isEnter=true'];
  2055. false ->
  2056. Module
  2057. end,
  2058. Format =
  2059. lists:append(
  2060. ["** gen_ipc State machine ", P, " terminating~n",
  2061. case Q of
  2062. [] -> "";
  2063. _ -> "** Last event = " ++ P ++ "~n"
  2064. end,
  2065. "** When server status = ", P, "~n",
  2066. "** Reason for termination = ", P, ":", P, "~n",
  2067. "** Callback modules = ", P, "~n",
  2068. "** Callback mode = ", P, "~n",
  2069. case Q of
  2070. [_, _ | _] -> "** Queued = " ++ P ++ "~n";
  2071. _ -> ""
  2072. end,
  2073. case Postponed of
  2074. [] -> "";
  2075. _ -> "** Postponed = " ++ P ++ "~n"
  2076. end,
  2077. case FixedStacktrace of
  2078. [] -> "";
  2079. _ -> "** Stacktrace =~n** " ++ P ++ "~n"
  2080. end,
  2081. case Timeouts of
  2082. {0, _} -> "";
  2083. _ -> "** Time-outs: " ++ P ++ "~n"
  2084. end,
  2085. case Log of
  2086. [] -> "";
  2087. _ -> "** Log =~n** " ++ P ++ "~n"
  2088. end]),
  2089. Args0 =
  2090. [Name |
  2091. case Q of
  2092. [] -> [];
  2093. [Event | _] -> [Event]
  2094. end] ++
  2095. [FmtData,
  2096. Class, FixedReason,
  2097. Module,
  2098. CBMode] ++
  2099. case Q of
  2100. [_ | [_ | _] = Events] -> [Events];
  2101. _ -> []
  2102. end ++
  2103. case Postponed of
  2104. [] -> [];
  2105. _ -> [Postponed]
  2106. end ++
  2107. case FixedStacktrace of
  2108. [] -> [];
  2109. _ -> [FixedStacktrace]
  2110. end ++
  2111. case Timeouts of
  2112. {0, _} -> [];
  2113. _ -> [Timeouts]
  2114. end ++
  2115. case Log of
  2116. [] -> [];
  2117. _ -> [Log]
  2118. end,
  2119. Args =
  2120. case Depth of
  2121. unlimited ->
  2122. Args0;
  2123. _ ->
  2124. lists:flatmap(fun(A) -> [A, Depth] end, Args0)
  2125. end,
  2126. {Format ++ ClientFmt, Args ++ ClientArgs}.
  2127. fix_reason(Class, Reason, Stacktrace) ->
  2128. case Stacktrace of
  2129. [{M, F, Args, _} | ST]
  2130. when Class =:= error, Reason =:= undef ->
  2131. case code:is_loaded(M) of
  2132. false ->
  2133. {{'module could not be loaded', M}, ST};
  2134. _ ->
  2135. Arity =
  2136. if
  2137. is_list(Args) ->
  2138. length(Args);
  2139. is_integer(Args) ->
  2140. Args
  2141. end,
  2142. case erlang:function_exported(M, F, Arity) of
  2143. true ->
  2144. {Reason, Stacktrace};
  2145. false ->
  2146. {{'function not exported', {M, F, Arity}}, ST}
  2147. end
  2148. end;
  2149. _ -> {Reason, Stacktrace}
  2150. end.
  2151. format_client_log_single(undefined, _, _) ->
  2152. {"", []};
  2153. format_client_log_single({Pid, dead}, _, _) ->
  2154. {" Client ~0p is dead.", [Pid]};
  2155. format_client_log_single({Pid, remote}, _, _) ->
  2156. {" Client ~0p is remote on node ~0p.", [Pid, node(Pid)]};
  2157. format_client_log_single({_Pid, {Name, Stacktrace0}}, P, Depth) ->
  2158. %% Minimize the stacktrace a bit for single line reports. This is
  2159. %% hopefully enough to point out the position.
  2160. Stacktrace = lists:sublist(Stacktrace0, 4),
  2161. Format = lists:append([" Client ", P, " stacktrace: ", P, "."]),
  2162. Args =
  2163. case Depth of
  2164. unlimited ->
  2165. [Name, Stacktrace];
  2166. _ ->
  2167. [Name, Depth, Stacktrace, Depth]
  2168. end,
  2169. {Format, Args}.
  2170. format_client_log(undefined, _, _) ->
  2171. {"", []};
  2172. format_client_log({Pid, dead}, _, _) ->
  2173. {"** Client ~p is dead~n", [Pid]};
  2174. format_client_log({Pid, remote}, _, _) ->
  2175. {"** Client ~p is remote on node ~p~n", [Pid, node(Pid)]};
  2176. format_client_log({_Pid, {Name, Stacktrace}}, P, Depth) ->
  2177. Format = lists:append(["** Client ", P, " stacktrace~n** ", P, "~n"]),
  2178. Args =
  2179. case Depth of
  2180. unlimited ->
  2181. [Name, Stacktrace];
  2182. _ ->
  2183. [Name, Depth, Stacktrace, Depth]
  2184. end,
  2185. {Format, Args}.
  2186. p(#{single_line := Single, depth := Depth, encoding := Enc}) ->
  2187. "~" ++ single(Single) ++ mod(Enc) ++ p(Depth);
  2188. p(unlimited) ->
  2189. "p";
  2190. p(_Depth) ->
  2191. "P".
  2192. single(true) -> "0";
  2193. single(false) -> "".
  2194. mod(latin1) -> "";
  2195. mod(_) -> "t".
  2196. %% Call Module:format_status/2 or return a default value
  2197. format_status(Opt, PDict, _Parent, _Name, Module, _HibernateAfterTimeout, _IsEnter, _EpmHers, _Postponed, _Timers, CurStatus, CurState) ->
  2198. case erlang:function_exported(Module, formatStatus, 2) of
  2199. true ->
  2200. try Module:formatStatus(Opt, [PDict, CurStatus, CurState])
  2201. catch
  2202. throw:Result -> Result;
  2203. _:_ ->
  2204. format_status_default(Opt, {{CurStatus, CurState}, atom_to_list(Module) ++ ":formatStatus/2 crashed"})
  2205. end;
  2206. false ->
  2207. format_status_default(Opt, {CurStatus, CurState})
  2208. end.
  2209. %% The default Module:format_status/3
  2210. format_status_default(Opt, State_Data) ->
  2211. case Opt of
  2212. terminate ->
  2213. State_Data;
  2214. _ ->
  2215. [{data, [{"State", State_Data}]}]
  2216. end.
  2217. print_event(Dev, SystemEvent, Name) ->
  2218. case SystemEvent of
  2219. {in, Event, Status} ->
  2220. io:format(
  2221. Dev, "*DBG* ~tp receive ~ts in Status ~tp~n",
  2222. [Name, event_string(Event), Status]);
  2223. {code_change, Event, Status} ->
  2224. io:format(
  2225. Dev, "*DBG* ~tp receive ~ts after code change in Status ~tp~n",
  2226. [Name, event_string(Event), Status]);
  2227. {out, Reply, {To, _Tag}} ->
  2228. io:format(
  2229. Dev, "*DBG* ~tp send ~tp to ~tw~n",
  2230. [Name, Reply, To]);
  2231. {out, Replys} ->
  2232. io:format(
  2233. Dev, "*DBG* ~tp sends to: ~tp~n",
  2234. [Name, Replys]);
  2235. {enter, Status} ->
  2236. io:format(
  2237. Dev, "*DBG* ~tp enter in Status ~tp~n",
  2238. [Name, Status]);
  2239. {start_timer, Action} ->
  2240. io:format(
  2241. Dev, "*DBG* ~tp start_timer ~tp ~n",
  2242. [Name, Action]);
  2243. {insert_timeout, Event, Status} ->
  2244. io:format(
  2245. Dev, "*DBG* ~tp insert_timeout ~tp in Status ~tp~n",
  2246. [Name, Event, Status]);
  2247. {terminate, Reason, Status} ->
  2248. io:format(
  2249. Dev, "*DBG* ~tp terminate ~tp in Status ~tp~n",
  2250. [Name, Reason, Status]);
  2251. {change_isEnter, IsEnter} ->
  2252. io:format(
  2253. Dev, "*DBG* ~tp change_isEnter to ~tp ~n",
  2254. [Name, IsEnter]);
  2255. {Tag, Event, Status, NextStatus}
  2256. when Tag =:= postpone; Tag =:= consume ->
  2257. StateString =
  2258. case NextStatus of
  2259. Status ->
  2260. io_lib:format("~tp", [Status]);
  2261. _ ->
  2262. io_lib:format("~tp => ~tp", [Status, NextStatus])
  2263. end,
  2264. io:format(
  2265. Dev, "*DBG* ~tp ~tw ~ts in state ~ts~n",
  2266. [Name, Tag, event_string(Event), StateString]);
  2267. _NotMatch ->
  2268. io:format(
  2269. Dev, "*DBG* ~tp NotMatch ~tp ~n",
  2270. [Name, _NotMatch])
  2271. end.
  2272. event_string(Event) ->
  2273. case Event of
  2274. {{call, {Pid, _Tag}}, Request} ->
  2275. io_lib:format("call ~tp from ~tw", [Request, Pid]);
  2276. {EventType, EventContent} ->
  2277. io_lib:format("~tw ~tp", [EventType, EventContent])
  2278. end.
  2279. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% debug 日志 End %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%