Erlang学习:OTP - Application & supervisor & gen_server

资料来源:http://blog.bot.co.za/en/article/349/an-erlang-otp-tutorial-for-beginners#.Upo4SWSOGJY

代码如下:

src/hello_server.erl

%%%----------------------------------------------------------------------------
%%% @doc An OTP gen_server example
%%% @author Hans Christian v. Stockhausen <hc at vst.io>
%%% @end
%%%----------------------------------------------------------------------------

-module(hello_server).         % Nothing new in this section except for the
                               %  next line where we tell the compiler that
-behaviour(gen_server).        %  this module implements the gen_server
                               %  behaviour. The compiler will warn us if
-define(SERVER, ?MODULE).      %  we do not provide all callback functions
                               %  the behaviour announces. It knows what
-record(state, {count}).       %  functions to expect by calling 
                               %  gen_server:behaviour_info(callbacks). Try it.
%%-----------------------------------------------------------------------------
%% API Function Exports
%%-----------------------------------------------------------------------------

-export([                      % Here we define our API functions as before 
  start_link/0,                % - starts and links the process in one step
  stop/0,                      % - stops it
  say_hello/0,                 % - prints "Hello" to stdout
  get_count/0]).               % - returns the count state

%% ---------------------------------------------------------------------------
%% gen_server Function Exports
%% ---------------------------------------------------------------------------

-export([                      % The behaviour callbacks
  init/1,                      % - initializes our process
  handle_call/3,               % - handles synchronous calls (with response)
  handle_cast/2,               % - handles asynchronous calls  (no response)
  handle_info/2,               % - handles out of band messages (sent with !)
  terminate/2,                 % - is called on shut-down
  code_change/3]).             % - called to handle code changes

%% ---------------------------------------------------------------------------
%% API Function Definitions
%% ---------------------------------------------------------------------------

start_link() ->                % start_link spawns and links to a new 
    gen_server:start_link(     %  process in one atomic step. The parameters:
      {local, ?SERVER},        %  - name to register the process under locally
      ?MODULE,                 %  - the module to find the init/1 callback in 
      [],                      %  - what parameters to pass to init/1
      []).                     %  - additional options to start_link

stop() ->                      % Note that we do not use ! anymore. Instead
    gen_server:cast(           %  we use cast to send a message asynch. to
      ?SERVER,                 %  the registered name. It is asynchronous
      stop).                   %  because we do not expect a response.

say_hello() ->                 % Pretty much the same as stop above except
    gen_server:cast(           %  that we send the atom say_hello instead.
      ?SERVER,                 %  Again we do not expect a response but
      say_hello).              %  are only interested in the side effect.

get_count() ->                 % Here, on the other hand, we do expect a 
    gen_server:call(           %  response, which is why we use call to
      ?SERVER,                 %  synchronously invoke our server. The call 
      get_count).              %  blocks until we get the response. Note how
                               %  gen_server:call/2 hides the send/receive
                               %  logic from us. Nice.
%% ---------------------------------------------------------------------------
%% gen_server Function Definitions
%% ---------------------------------------------------------------------------

init([]) ->                    % these are the behaviour callbacks. init/1 is
    {ok, #state{count=0}}.     % called in response to gen_server:start_link/4
                               % and we are expected to initialize state.

handle_call(get_count, _From, #state{count=Count}) -> 
    {reply, 
     Count,                    % here we synchronously respond with Count
     #state{count=Count+1}     % and also update state
    }.

handle_cast(stop, State) ->    % this is the first handle_case clause that
    {stop,                     % deals with the stop atom. We instruct the
     normal,                   % gen_server to stop normally and return
     State                     % the current State unchanged.
    };                         % Note: the semicolon here....

handle_cast(say_hello, State) -> % ... becuase the second clause is here to
    io:format("Hello~n"),      % handle the say_hello atom by printing "Hello"
    {noreply,                  % again, this is asynch, so noreply and we also
    #state{count=
      State#state.count+1}
    }.                         % update our state here

handle_info(Info, State) ->      % handle_info deals with out-of-band msgs, ie
    error_logger:info_msg("~p~n", [Info]), % msgs that weren't sent via cast
    {noreply, State}.          % or call. Here we simply log such messages.

terminate(_Reason, _State) ->  % terminate is invoked by the gen_server
    error_logger:info_msg("terminating~n"), % container on shutdown.
    ok.                        % we log it and acknowledge with ok.

code_change(_OldVsn, State, _Extra) -> % called during release up/down-
    {ok, State}.               % grade to update internal state. 

%% ------------------------------------------------------------------
%% Internal Function Definitions
%% ------------------------------------------------------------------

% we don't have any.

src/hello_sup.erl

-module(hello_sup).

-behaviour(supervisor).

%% API
-export([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).

%% ===================================================================
%% API functions
%% ===================================================================

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

%% ===================================================================
%% Supervisor callbacks
%% ===================================================================

init([]) ->
    RestartStrategy = one_for_one,
    MaxRestarts = 1000,
    MaxSecondsBetweenRestarts = 3600,

    SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},

    Restart = permanent,
    Shutdown = 2000,
    Type = worker,

    AChild = {hello_server, {hello_server, start_link, []},
          Restart, Shutdown, Type, [hello_server]},

    {ok, {SupFlags, [AChild]}}.

src/hello_app.erl

-module(hello_app).

-behaviour(application).

%% Application callbacks
-export([start/2, stop/1]).

%% ===================================================================
%% Application callbacks
%% ===================================================================

start(_StartType, _StartArgs) ->
    hello_sup:start_link().

stop(_State) ->
    ok.

ebin/hello.app

{application,hello,
  [{description,[]},
   {vsn,"1"},
   {registered,[]},
   {applications,[kernel,stdlib]},
   {mod,{hello_app,[]}},
   {env,[]},
   {modules,[hello_app,hello_server,hello_sup]}]}.

运行代码:

erl -pa ebin

1> application:start(hello).
ok
2> whereis(hello_sup).
<0.37.0>
3> whereis(hello_server).
<0.38.0>
4> hello_server:say_hello().
Hello
ok
5> application:stop(hello).

=INFO REPORT==== 17-Dec-2012::15:37:47 ===
    application: hello
    exited: stopped
    type: temporary
ok
6> whereis(hello_sup).
undefined
7> whereis(hello_server).
undefined


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值