Erlang OTP gen_server起步

Erlang OTP/gen_server实现简单频道服务,没有用ETS表存储,在record中更新;

1、alloc/0:获取一个空闲频道,

2、free/1:释放一个已经使用的频道

gen_server:start_link({local,?MODULE},?MODULE,..):启动一个本地服务器

gen_server:call(?Module,Term):对服务器的远程调用

handle_call/3:和gen_server:call之间交互实现RPC

handle_info/2:处理发给服务器的原生消息

terminate/2:服务器终止调用函数

code_change/3:热代码替换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
-module(channel_server).
-export([start/0]).
-export([alloc/0, free/1, stop/0]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
		terminate/2, code_change/3]).
-behaviour(gen_server).
-record(channel,{allocated, free}).

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

alloc() -> gen_server:call(?MODULE, {alloc}).    %% 获取一个空闲频道
free(Ch)-> gen_server:call(?MODULE, {free, Ch}). %% 释放一个已用频道
stop()  -> gen_server:call(?MODULE, stop).

init([]) ->  %% 初始化allocated:已用频道;free:空闲频道
	{ok, #channel{allocated = [], free = lists:seq(1,50)}}.

handle_call({alloc}, _From, Start) ->
	%% io:format("alloc:==="),
	{Allocated, [H|T]} = {Start#channel.allocated, Start#channel.free},
	Reply = [H|Allocated],
	NewStart = Start#channel{allocated=Reply, free=T},
	{reply, Reply, NewStart};

handle_call({free, Ch}, _From, Start) ->
	{Alloc, Free} = {Start#channel.allocated, Start#channel.free},
	{_, Reply} = case lists:member(Ch, Alloc) of
		true ->
			A = lists:delete(Ch, Alloc),
			B = [Ch|Free],
			NewStart = Start#channel{allocated=A, free=B},
			{A, B};
		false ->
			NewStart = Start#channel{allocated=Alloc, free=Free},
			{Alloc, Free}
	end,
	{reply, Reply, NewStart};

handle_call(stop, _From, Start) ->
	{stop, normal, stoped, Start}.

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

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

terminate(_Reason, _Start) ->
	ok.

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

参考