ErrlangにおけるModuleレベルの熱い展開


Javaの中でCode Replaccementを実現します。つまりどんな熱い展開ですか?通常はClass Loaderの機構を使います。先日GoogleのPaperを見ましたが、中で説明しているC++コードの熱い展開はもっと複雑です。
Errlangでは、Code Replaccementを実現するのは簡単です。一番便利な方法は「Elang Reference Manual」の12.3を参照することができます。
-module(m).
-export([loop/0]).

loop() ->
    receive
        code_switch ->
            m:loop();
        Msg ->
            ...
            loop()
    end.
このような簡単なハローワールドの例は、私の疑問を満たすことができません。もっと複雑なアプリケーションの中で、例えば複数のProcessがありますが、一部のProcessのコードが変更された後、他の更新されていないProcessはどうなりますか?次はテストをします。
実例コード:coderload.erl
-module(codereload).
-export([main/0, master_loop/2, worker_loop/0]).
-define(VERSION, "0.1").

main() ->
    process_flag(trap_exit, true),
    Pid1 = spawn(?MODULE, worker_loop, []),
    Pid2 = spawn(?MODULE, worker_loop, []),
    spawn(fun() -> register(master, self()), master_loop(Pid1, Pid2) end).


master_loop(Pid1, Pid2) ->
    io:format("Pid1, Pid2 is alive ~p ~p~n",[is_process_alive(Pid1), is_process_alive(Pid2)]),
    receive
	refresh ->
	    io:format("Master code reload~n"),
	    Pid1 ! refresh,
	    Pid2 ! refresh,
	    codereload:master_loop(Pid1, Pid2);
	Any ->
	    io:format("Master ~p receive message: ~p~n", [?VERSION, Any]),
	    Pid1 ! Any,
	    Pid2 ! Any,
	    master_loop(Pid1, Pid2)
    end.

worker_loop() ->
    receive
	refresh ->
	    io:format("Worker code ~p reload~n", [self()]),
	    codereload:worker_loop();
	Any ->
	    io:format("Worker ~p at ~p also receive message: ~p~n", [?VERSION, self(), Any]),
	    worker_loop()
    end.
プログラムの中には三つのプロセスがあります。一つのマスターと二つのWorkerがあります。次は分散プロセス通信を使ってCode Replaccementを実現します。
使用
参照
erl-snamefoo@localhost
erl-snamebar@localhost
起動erlang shell
スタートコード:
参照
(foo@localhost)1>コデルロード:main().
Pid 1,Pid 2 is alive true true
<0.39.0>
「HI」を送ってみます。
参照
(bar@localhost)1>{マスター、'foo@localhost'}HIです
HI
はい、受け取りました
参照
(foo@localhost)2>マスター「0.1」receive message:「HI」
(foo@localhost)2>Pid 1、Pid 2 is alive true true
(foo@localhost)2>Workカー“0.1”at<0.37.0>also receive message:“HI”
(foo@localhost)2>Workカー“0.1”at<0.38>also receive message:“HI”
はい、ソースを変更してください。
-define(VERSION, "0.1"). --> -define(VERSION, "0.2").
Pid2 ! refresh, --> %Pid2 ! refresh,
ここでバージョン番号を変更しました。そして、コメントを落としてPid 2に送る更新通知があります。
先に新しいバージョンをコンパイルします
参照
(foo@localhost)2>c(coderload)
{ok,coderload}
更新通知を送信:
参照
(bar@localhost)2>{マスター、'foo@localhost'}refresh.
refresh
受信しました:
参照
(foo@localhost)3>マスターコードreload
(foo@localhost)3>ワードコード<0.37.70>reload
(foo@localhost)3>Workカーコード<0.38>reload
(foo@localhost)3>Pid 1、Pid 2 is alive true true
この時マスター、Pid 1、Pid 2は全部v 0.2バージョンであるはずです。
参照
(bar@localhost)3>{マスター、'foo@localhost'}HIです
HI
参照
(foo@localhost)3>マスター「0.2」receive message:「HI」
(foo@localhost)3>Pid 1、Pid 2 is alive true true
(foo@localhost)3>Workカー“0.2”at<0.37.0>also receive message:“HI”
(foo@localhost)3>Workカー“0.2”at<0.38>also receive message:“HI”
OK、「0.2」に変更しました。コードの交換に成功しました。仕事はまだ終わっていません。上の人に注意してください。refreshが注釈を落としましたか?この時の更新はどうなりますか?先にプログラムを変更します
-define(VERSION, "0.2"). --> -define(VERSION, "0.3").
%Pid2 ! refresh, --> Pid2 ! refresh,
再コンパイル:
参照
(foo@localhost)3>c(coderload)
{ok,coderload}
更新通知を送信:
参照
(bar@localhost)7>{マスター、'foo@localhost'}refresh.
refresh
参照
(foo@localhost)4>マスターコードreload
(foo@localhost)4>Workカーコード<0.37.70>reload
(foo@localhost)4>Pid 1、Pid 2 is alive true true
今はPid 1だけ更新通知を受けて更新していますが、どのような結果が出るのでしょうか?
参照
(bar@localhost)8>{マスター、'foo@localhost'}HIです
HI
参照
(foo@localhost)4>マスター「0.3」receive message:「HI」
(foo@localhost)4>Pid 1、Pid 2 is alive true true
(foo@localhost)4>Workカー「0.3」at<0.37.0>also receive message:「HI」
(foo@localhost)4>Workカー「0.2」at<0.38>also receive message:「HI」
えっと、Pid 2はまだv 0.2のコードに留まっています。各プロセスのコードは独立しています。
更新通知を送ります。Pid 2にv 0.3のコードをロードさせます。
参照
(bar@localhost)8>{マスター、'foo@localhost'}refresh.
refresh
参照
(foo@localhost)4>マスターコードreload
(foo@localhost)4>Workカーコード<0.37.70>reload
(foo@localhost)4>Workカーコード<0.3800>reload
(foo@localhost)4>Pid 1、Pid 2 is alive true true
今回はPid 2が新しいバージョンに更新されました。
(bar@localhost)9> {master, 'foo@localhost'} ! "HI".
"HI"
参照
(foo@localhost)4>マスター「0.3」receive message:「HI」
(foo@localhost)4>Pid 1、Pid 2 is alive true true
(foo@localhost)4>Workカー「0.3」at<0.37.0>also receive message:「HI」
(foo@localhost)4>Workカー「0.3」at<0.38>also receive message:「HI」
目眩がしますか?私も酔いました。もう一つの状況があります。上にあります
参照
(foo@localhost)4>マスター「0.3」receive message:「HI」
(foo@localhost)4>Pid 1、Pid 2 is alive true true
(foo@localhost)4>Workカー「0.3」at<0.37.0>also receive message:「HI」
(foo@localhost)4>Workカー「0.2」at<0.38>also receive message:「HI」
このステップは、入力しないと
参照
{マスター、}foo@localhost'}refresh.
再コンパイルです。
参照
(foo@localhost)4>c(coderload)
{ok,coderload}
メッセージを送って行ってみます。
(bar@localhost)9> {master, 'foo@localhost'} ! "HI".
"HI"
参照
(foo@localhost)5>マスター「0.3」receive message:「HI」
(foo@localhost)5>Pid 1,Pid 2 is alive true false
(foo@localhost)5>Workカー“0.3”at<0.37.0>also receive message:“HI”
えっと、どういうことですか?is_。process.alive(Pid 2)はfalseに戻りましたが、プロセスはどうなりましたか?
Errlang Reference Manualの12.3:
参照
The code of a module can exist in two variants in a system:current and old.When a module is loaded into the system for the first time,the code becode berrent'.If then a new instance of the modunce the modunce's the modunce of the modunce the the modunce of the the modunce's。
Bot old and current code is valid,and may be evaluated concurrently.Fuly qualifed function cars always refer to current code.Old code may still be evaluted because of processes linggering the old.code.code.
If a third instance of the module is loaded、the code server will remove the old code and any processes lingering in it will be terminated.The n the third instance becorrent'and the previours corevent correct's.correns.co corrence。
エリンランドでは、モジュールのコードは新旧の2つのバージョンしかありません。Pid 1はv 0.3に対応しています。Pid 2はv 0.2(Old)に対応しています。コンパイルすると、Pid 1のコードはOldです。Pid 2は強制的に終了されます。
守護プロセスとして起動したエラランプロセスは、シェル内で直接コンパイルすることはできません。外部でコンパイルすれば、このプロセスは認識されません。私が考えている方法はrpcを使ってコンパイルを呼び出すことです。
rpc:call('foo@localhost',shelludfault,c,[COdeload])
熱い展開に対して、Elangはもう一つの強い形式があります。OTPを使うRelease Handlingもできません。これから勉強します。
p.s:本論文に対して何か異議があります。チェキを歓迎します。)