環境と後処理

blenderでskyを作ることができる。

#Erlang

tty

tty

シェルブレイクモード

Erlangのシェルを操作するためのモードだと思われる。複数のシェルを起動したり、その切り替えをすることができる。

C-gでシェルブレイクモードに入る。hでヘルプ。

exit/2

他のプロセスを終了するにはexit/2を使う。

終了させられる側のプロセスがprocess_flag/2trap_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).

タイマー