読者です 読者をやめる 読者になる 読者になる

simple_one_for_one が素晴らしい

今更すぎて、それ常識だよねと言われそう。

simple_one_for_one を superviosr で使った場合 superviosr:start_child で渡した引数は、
superviosr 側で設定した init の 呼び出されるモジュールに ++ されるということを知った。

ドキュメントの OTP Design Principles の 5.9 Simple-One-For-One Supervisors に書いてある ... 。

これを使うと別の behaviour から supervisor:start_child したとき気軽に引数として渡せて素晴らしく楽。
つまるところ ListenSocket を Acceptor に渡すと気楽だよね、という話しで終わるわけですが。

未来の自分のためにソースコードと解説を張っておく。

rabbitmq-server-1.5.4/src/tcp_acceptor_sup.erl をコピペ

-module(tcp_acceptor_sup).

-behaviour(supervisor).

-export([start_link/2]).

-export([init/1]).

start_link(Name, Callback) ->
    supervisor:start_link({local,Name}, ?MODULE, Callback).

init(Callback) ->
    {ok, {{simple_one_for_one, 10, 10},
          [{tcp_acceptor, {tcp_acceptor, start_link, [Callback]},
            transient, brutal_kill, worker, [tcp_acceptor]}]}}.

上記の {tcp_acceptor, {tcp_acceptor, start_link, [Callback]} で tcp_acceptor:start_link に渡る引数はコードの見かけ上は Callback だけだが、実は tcp_aceptor_sup を引っ張ってる tcp_listener.erl に仕掛けがある。

rabbitmq-server-1.5.4/src/tcp_listener.erl からコピペ

{ok, _APid} = supervisor:start_child(AcceptorSup, [LSock])

ここの supervisor:start_child(sup, [LSock]) で渡している LSock が tcp_acceptor の start_link に Callback に付け加えられる。
[Callback] ++ [LSock] という形で引数が渡される。実際、tcp_acceptor のコードを見てみるとよくわかる。

rabbitmq-server-1.5.4/src/tcp_acceptor.erl

start_link(Callback, LSock) ->
    gen_server:start_link(?MODULE, {Callback, LSock}, []).

tcp_acceptor_sup:init では Callback しか無かったにもかかわらず LSock が足されている。これは素晴らしい。

結論は tcp_listner から tcp_acceptor_sup へ supervisor:start_child(sup, [LSock]) すれば簡単に LSock を渡せるということ。

未来の自分、理解できましたか。

ソースコードについて

ここに貼り付けたソースコードは RabbitMQ のサイトで公開されている物で、モジラライセンスで公開されている物です。
私が書いたコードではありませんので、ライセンスは RabbitMQ にあります。