erlang程序設計裏面有個設計原則就是把你的進程構造成樹,把共用代碼提出來,特定功能用自己的module實現,這也就是behaviour了,應用behaviour可以減少與本身事務無關的代碼量,設計邏輯更加清晰。老紀邊學習邊記錄吧。
gen_server實現服務器/客戶端模型,用於多個客戶共用一個資源的這種情況。他由幾個接口函數和幾個回調函數組成(回調函數必須在你的module裏定義)這些可以參考erlang的doc
舉個例子:
-module(ch3). %這是我們的回調模塊,也是我們實現業務邏輯的模塊-behaviour(gen_server). %說明我們應用gen_server這個behaviour-export([start_link/0]). %-export([alloc/0, free/1]). -export([init/1, handle_call/3, handle_cast/2]). %gen_server 的導出函數 start_link() -> gen_server:start_link({local, ch3}, ch3, [], []). alloc() -> gen_server:call(ch3, alloc). free(Ch) -> gen_server:cast(ch3, {free, Ch}). init(_Args) -> {ok, channels()}. handle_call(alloc, _From, Chs) -> {Ch, Chs2} = alloc(Chs), {reply, Ch, Chs2}. handle_cast({free, Ch}, Chs) -> Chs2 = free(Ch, Chs), {noreply, Chs2}.
gen_server:start_link的調用會生成一個服務器進程且連接到進程樹,並調用我們的init函數。
gen_server:call(ch3, alloc)的調用導致對handle_call的調用,這是同步的。
gen_server:cast(ch3, {free, Ch})的調用導致對handle_cast的調用,這是異步的。很簡單。
假如你不想把服務器進程掛入監控樹的話,直接用gen_server:start啓動進程,這是這個服務器進程就是一個普通進程了。
gen_server的停止規則:
1. 以gen_server:start_link開始的連入監控樹:
一般情況不需要提供自己的停止函數,監控進程會自動處理,但是如果你想在gen_server進程中自己清理以下資源,那麼就必須在init函數裏調 用process_flag(trap_exit, true)來捕獲退出信號,這會導致調用terminate(shutdown, State)函數,所以你也必須實現這個函數
2. 以gen_server:start開始的單獨gen_server:
終止他就比較簡單,直接調用gen_server:cast(Name, stop),這會導致調用handle_cast(stop, State),它的實現裏寫入 {stop, normal, State}即可,它最終導致terminate(normal, State)的調用,你的清理工作就可以在這繼續了。
erlang越看越喜歡,但是要深入要走的路還很長
本文屬轉載
原作者:老紀
原載:老紀博客版權所有。轉載時必須以鏈接形式註明轉載自老紀博客 [http://www.jifuyi.com/]。