mini gen_server(它是怎么工作的)

Joe Armstrong:

许多用户常常使用gen_server似乎认为它能够解决所有事情,并且尝试强制他们的问题适用于gen_server,尽管gen_server不适合他们的问题。

gen_server是一个非常简单的代码,可以很容易的改变它,以适用于其他问题,然而人们并不常常这样做。

在这篇文章中,我将介绍gen_server的工作原理。

为了说明这一点,我写了mini_gs.erl,如果你能明白mini_gs,这是一个迷你gen_server。你会明白98%的gen_server真实工作情况,真正的gen_server只是在mini_gs的基础上添加了一些华而不实的东西。

mini_gs.erl具有与gen_server.erl的兼容接口(gen_server API的一个子集)

-module(mini_gs).
-export([start_link/4, call/2]).

%% this module behaves just like the gen-server for a sub-set of the gen_server
%% commands
start_link({local,Name}, Mod, Args, _Opts) ->
    register(Name, spawn(fun() -> start(Mod, Args) end)).
call(Name, X) ->
    Name ! {self(), Ref = make_ref(), X},
    receive
     {Ref, Reply} -> Reply
    end.
start(Mod, Args) ->
   {ok, State} = Mod:init(Args),
   loop(Mod, State).
loop(Mod, State) ->
   receive
   {From, Tag, X} ->
      case Mod:handle_call(X, From, State) of
      {reply, R, State1} ->
          From ! {Tag, R},
          loop(Mod, State1)
      end
  end.

这里没有那么麻烦,客户端通过调用mini_gs:start_link({local,Name},Mod,Args,Opts)开始

我忽略了mini_gs中的选项,也固定了server的名称格式{local,Name}gen_server对于server的名称有更多的一般参数)

接下来什么发生了

mini_gs调用了Mod:init(Args)用来初始化server,这要求返回{ok,State},
并且State成为服务的初始状态。

现在mini_gs调用 loop(Mod,State) 。当mini_gs
收到{From,Tag,X}消息,会调用Mod:handle_call(X,From,State ),这要求返回{reply,R,State1}。R1会返回给客户端,服务器以新的状态State1调用loop/2

仅此而已,call/2是一个接口程序,用来抽象出客户端和服务端之间的接口。

现在我们可以编写一个简单的客户端应用。

-module(kv).
%% These define the client API
-export([start/0, store/2,lookup/1]).
%% these must be defined because they are called by gs
-export([init/1, handle_call/3]).
-define(GS, mini_gs).
%% -define(GS, gen_server).
%% define the client API
start()        -> ?GS:start_link({local,someatom}, kv, foo, []).
store(Key,Val) -> ?GS:call(someatom, {putval,Key,Val}).
lookup(Key)    -> ?GS:call(someatom, {getval,Key}).
%% define the internal routines
init(foo) -> {ok, dict:new()}.
handle_call({putval, Key, Val}, _From, Dict) ->
   {reply, ok, dict:store(Key, Val, Dict)};
handle_call({getval,Key}, _From, Dict) ->
  {reply, dict:find(Key, Dict), Dict}.

该模块可以调用gen_servermini_gs(只需要修改define声明)

所以现在我们已经把一个单一键值存储进程(使用dict)转换成了全局key-value存储。请注意kv.erl并没有使用原语spawn_link发送、接收、或在此基础上。即kv.erl是用纯序列代码编写的。

这是为什么我们做了gen_server抽象。你可以编写良好的顺序代码(handle_callinit函数)进行参数化并发行为,即你完成工作却并不需要了解并发性。我们已经"抽象出"了并发性。

当你完全不理解抽象部分的时候,事情变得有问题。也许抽象的不适合你的需要。我曾经看到很多这样的例子,其中gen_server是不合适的。关键性的测试使gen_server代码看起来显示格式意大利面条一样杂乱无序,如果是这样的,那么所有你做的是使应用成为不适当的形式,像不合适的鞋码一样蹩脚,你应该挖掘gen_server定制为你自己的。

参考:Joe amstrong的mail
链接:找回自己

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容