专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > Erlang

Erlang入门:gen_server范例操作与练习1

发布时间:2011-06-29 17:49:05 文章来源:www.iduyao.cn 采编人员:星星草
Erlang入门:gen_server实例操作与练习1
%% @author Rolong<rolong@vip.qq.com>

-module(bank_test1).
-compile(export_all).

%% 假设我开了3个银行账户:
%%
%% bank_server2:create_account(name1, 100).
%% bank_server2:create_account(name2, 100).
%% bank_server2:create_account(name3, 100).
%%
%% 练习1:如何获取name1对应的pid?
%%
%% 解答1:Pid1 = whereis(name1).
%%
%%
%% 练习2:实现一个函数,计算以上3个账户余额的总和。
%%
%% bank_sum(name1, name2, name3) -> Result.
%%
%% Result 为账号name1, name2, name3三个账户余额的总和。

%% 练习2解答思路:

%% 1、先实现获取一个账户余额的API

%% 1.1、用receive原语实现
bank_check(Name) ->
    Pid = whereis(Name),
    Pid ! {self(), check},
    receive
        {Pid, Money} -> Money
    end.

%% 1.2、用gen_server:call/2实现
bank_check2(Name) ->
    gen_server:call(Name, check).

%% 2、实现bank_sum函数

%% 2.1、普通实现
bank_sum(N1, N2, N3) ->
    M1 = bank_check2(N1),
    M2 = bank_check2(N2),
    M3 = bank_check2(N3),
    M1 + M2 + M3.

%% 2.2、递归实现
bank_sum2(Names) ->
    bank_sum2(Names, 0).

bank_sum2([Name | T], Sum) ->
    Sum1 = Sum + bank_check2(Name),
    bank_sum2(T, Sum1);
bank_sum2([], Sum) ->
    Sum.


-module(bank_server2).
-behaviour(gen_server).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([create_account/2]).

-define(I(F), io:format(F++"~n", [])).
-define(I(F, A), io:format(F++"~n", A)).

% --------------------------------------------------------------------
% API
% --------------------------------------------------------------------

%%'银行开户,并存入初始金额
-spec create_account(Name, Money) -> any() when
      Name :: atom(),
      Money :: integer().

create_account(Name, Money)->
    %% gen_server:start(Mod, Args, Options)
    {ok, Pid} = gen_server:start(?MODULE, [Money], []),
    %% 假设年费为10
    Pid ! {yearly, 60},
    erlang:register(Name, Pid).

% --------------------------------------------------------------------
% Callback
% --------------------------------------------------------------------

init([Money]) ->
    {ok, Money}.

handle_call(check, _From, Money) ->
    {reply, Money, Money};

handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

%%'存钱
handle_info({deposit, AddMoney}, Money) ->
    NewMoney = Money + AddMoney,
    ?I("deposit money: ~w -> ~w", [Money, NewMoney]),
    {noreply, NewMoney};
%%.

%%'取钱(可透支)
handle_info({cash1, SubMoney}, Money) ->
    NewMoney = Money - SubMoney,
    ?I("deposit money: ~w -> ~w", [Money, NewMoney]),
    {noreply, NewMoney};
%%.

%%'取钱(不可透支)
handle_info({cash2, SubMoney}, Money) ->
    NewMoney = Money - SubMoney,
    case NewMoney > 0 of
        true ->
            %% 支取成功
            ?I("deposit money: ~w -> ~w", [Money, NewMoney]),
            {noreply, NewMoney};
        false ->
            %% 支取失败 提示余额不足
            ?I("Insufficient balance, current money is ~w", [Money]),
            {noreply, Money}
    end;
%%.

%%'扣年费(这里假设10秒为一年)
handle_info({yearly, Payment}, Money) ->
    Year = case get(year) of
        undefined -> 
            put(year, 0),
            0;
        Y -> 
            YY = Y + 1,
            put(year, YY),
            YY
    end,
    erlang:send_after(60 * 1000, self(), {yearly, Payment}),
    Reply = if 
        Money =< 0 ->
            %% 没有钱可以扣
            Money;
        Year =:= 0 ->
            %% 还不到一年,不用扣
            Money;
        true ->
            NewMoney = Money - Payment,
            case NewMoney > 0 of
                true ->
                    %% 扣费成功
                    ?I("Yearly Payment: ~w -> ~w", [Money, NewMoney]),
                    NewMoney;
                false ->
                    %% 余额不足以扣年费,则扣到0为止
                    ?I("Yearly Payment: ~w -> ~w", [Money, 0]),
                    0
            end
    end,
    {noreply, Reply};
%%.

%%'查询
handle_info(check, Money) ->
    ?I("Current money is: ~w", [Money]),
    {noreply, Money};

handle_info({From, check}, Money) ->
    %% ?I("Send result to: ~w", [From]),
    From ! {self(), Money},
    {noreply, Money};
%%.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: