动态加载代码,个人理解就是另外开一条进程A,初始化的时候,远程调用,发送一个函数f1发送过去,然后一直保持receive ,阻塞状状态。
举例说明
event_handler 为事件处理,可以理解为服务器,可以动态加载代码。
-module(event_handler).
-compile(export_all).
make(Name) ->
register(Name,spawn(fun() -> my_handler(fun no_op/1) end)).
my_handler(Fun) ->
receive
{add,Fun1} ->
my_handler(Fun1);
{event,Any} ->
(catch Fun(Any)),
my_handler(Fun)
end.
no_op(_) ->void.
add_handler(Name,Fun) ->
Name ! {add,Fun}.
event(Name,X) ->Name ! {event , X}.
motor_controller 为回调模块
-module(motor_controller).
-compile(export_all).
add_event_handler() ->
event_handler:add_handler(errors,fun controller/1).
controller(too_hot) ->
io:format("Turn off the motor~n");
controller(X) ->
io:format("~w ignored event:~p~n",[?MODULE,X]).
编译后执行加载代码,执行函数
很简单的代码,但是确实可以实现很强大的功能。
event_handler:make(errors)
这句分裂了一个进程A,且注册到了erlang的节点上,且传入了函数no_op,进程A在receive处阻塞。这个时候可以有两种选择
1. event(Name,X) ->Name ! {event , X}. 则可以发信息{event,hi}给A进程, A进程收到信息则不会再阻塞,执行no_op函数。
2.调用add_handler(Name,X) 方法,则可以发信息{add,fun controller/1}给A进程 ,A进程收到消息,匹配到了
{add,Fun1} ,则Fun1作为 myhandler的参数执行 myhandler(Fun1) ,再次回到了received的阻塞状态。这样一来就完成了动态代码加载。
如果是执行了2,event(Name,X) 这个里面的代码就换成了新的motor_controller里的代码了,
所以才会输出这一句。
如果不对,请指出批评。谢谢。