環境と後処理
blenderでskyを作ることができる。
#Erlang
tty
シェルブレイクモード
Erlangのシェルを操作するためのモードだと思われる。複数のシェルを起動したり、その切り替えをすることができる。
C-gでシェルブレイクモードに入る。hでヘルプ。
exit/2
他のプロセスを終了するにはexit/2を使う。
終了させられる側のプロセスがprocess_flag/2のtrap_exitを実装していた場合、メッセージが送られる。
モニター
1 -module(t).
2 -compile(export_all).
3
4 foo() ->
5 receive
6 bye -> exit(self());
7 s ->
8 P = spawn(?MODULE, bar, []),
9 monitor(process, P),
10 foo();
11 {Tag, MonitorRef, process, Object, Info} ->
12 io:format("--- ~w ~w ~w ~w ~n", [Tag, MonitorRef, Object, Info]),
13 foo()
14 end.
15
16
17 bar() ->
18 receive
19 after
20 3000 ->
21 io:format("--- ~w.~n", [self()]),
22 exit(self())
23 end.
24
25 start() ->
26 P = spawn(?MODULE, foo, []),
27 register(p, P).
register/2
参照
gen_server
1 -module(s).
2 -behaviour(gen_server).
3 -export([start_link/0]).
4 -export([init/1, handle_cast/2, handle_call/3, handle_info/2]).
5
6 start_link() ->
7 gen_server:start_link({local, s}, s, 0, []).
8
9 init(Args) ->
10 %process_flag(trap_exit, true),
11 io:format("---- init: ~w.~n", [Args]),
12 {ok, Args}.
13
14 handle_cast(Request, State) ->
15 timer:sleep(1000 * 3),
16 X = State + Request,
17 io:format("---- handle_cast: ~w ~w.~n", [Request, State]),
18 {noreply, X}.
19
20 handle_call(Request, From, State) ->
21 X = State + Request,
22 io:format("---- handle_call: ~w ~w ~w.~n", [Request, From, State]),
23 {reply, X, X}.
24
25 handle_info(Info, State) ->
26 io:format("---- handle_info: ~w.~n", [Info]),
27 {noreply, State}.
initは初期化。handle_castは非同期呼び出し(値を返すことはできない)。handle_callは同期呼び出し(値を返すことができる)。gen_server:cast(s, foo).のような形で呼び出す。
オプションだが、通常のメッセージ!を受信する必要がある場合はhandle_infoを使う。
サーバーを止めるにはgen_server:stop(s).のようにする。
手書きで書くのと比べて、状態を簡単に管理できるのが最大の特徴か。
supervisor
1 -module(sv).
2 -behaviour(supervisor).
3 -export([start_link/0]).
4 -export([init/1]).
5
6 start_link() ->
7 supervisor:start_link(sv, []).
8
9 init(_Args) ->
10 SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},
11 ChildSpecs = [#{id => s,
12 start => {s, start_link, []},
13 restart => permanent,
14 shutdown => brutal_kill,
15 type => worker,
16 module => [s]}],
17 {ok, {SupFlags, ChildSpecs}}.
省略可能なオプションを全て省略すると以下のようになる。大抵の場合はこれで問題なさそうではある。
1 -module(sv).
2 -behaviour(supervisor).
3 -export([start_link/0]).
4 -export([init/1]).
5
6 start_link() ->
7 supervisor:start_link(sv, []).
8
9 init(_Args) ->
10 SupFlags = #{},
11 ChildSpecs = [#{id => s, start => {s, start_link, []}}],
12 {ok, {SupFlags, ChildSpecs}}.
スーパーバイザーはサーバー、ステートマシン、イベントを自動的に再起動するために使う。ランタイムエラーなどの場合は再起動できない。
終了処理
sys, proc_lib
sysはシェルでのデバッグに使える。proc_libは標準以外のプロセスをOTP原則に準拠させるために使うようだ(あまり使うことはないだろう)。
アプリケーション
アプリケーションのモジュールadder_app.erlを作成する。とりあえず、引数は必要ないだろう。
1 -module(adder_app).
2 -behaviour(application).
3
4 -export([start/2, stop/1]).
5
6 start(_Type, _Args) ->
7 sv:start_link().
8
9 stop(_State) ->
10 ok.
アプリケーションの設定ファイルadder_app.appを作成する。
1 {application, adder_app,
2 [{mod, {adder_app, []}}]}.
アプリケーションを使用するにはシェルで以下のようにする。
1 1> application:start(adder_app).
2 2> application:stop(adder_app).
OTPディレクトリ構造
分散アプリケーション
コンパイルとロード
コンパイル。
1 compile:file(foo).
ロード。
1 code:load_file(foo).