Erlang 21 - 2. gen_server Behaviour

2 gen_server व्यवहार




erlang

2 gen_server व्यवहार

इस खंड को gen_server(3) में gen_server(3) मैनुअल पेज के साथ पढ़ा stdlib , जहाँ सभी इंटरफ़ेस फ़ंक्शंस और कॉलबैक फ़ंक्शंस का विस्तार से वर्णन किया गया है।

2.1 क्लाइंट-सर्वर सिद्धांत

क्लाइंट-सर्वर मॉडल की विशेषता केंद्रीय सर्वर और ग्राहकों की एक मनमानी संख्या है। क्लाइंट-सर्वर मॉडल का उपयोग संसाधन प्रबंधन कार्यों के लिए किया जाता है, जहां कई अलग-अलग ग्राहक एक सामान्य संसाधन साझा करना चाहते हैं। सर्वर इस संसाधन के प्रबंधन के लिए जिम्मेदार है।

चित्र 2.1: क्लाइंट-सर्वर मॉडल

२.२ उदाहरण

सादे Erlang में लिखे गए सरल सर्वर का एक उदाहरण Overview । इस कॉलबैक मॉड्यूल के परिणामस्वरूप, gen_server का उपयोग करके सर्वर को फिर से लागू किया जा सकता है:

-module(ch3).
-behaviour(gen_server).

-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1, handle_call/3, handle_cast/2]).

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}.

कोड को अगले खंडों में समझाया गया है।

2.3 एक Gen_Server शुरू करना

पिछले अनुभाग में उदाहरण में, gen_server को ch3:start_link() कहकर शुरू किया गया है:

start_link() ->
    gen_server:start_link({local, ch3}, ch3, [], []) => {ok, Pid}

start_link कॉल फ़ंक्शन gen_server:start_link/4 । यह फ़ंक्शन gen_server करता है और एक नई प्रक्रिया के लिंक देता है, एक gen_server

  • पहला तर्क, {local, ch3} , नाम निर्दिष्ट करता है। Gen_server को तब ch3 रूप में स्थानीय रूप से पंजीकृत किया जाता है।

    यदि नाम छोड़ा गया है, तो gen_server पंजीकृत नहीं है। इसके बजाय इसके पिड का उपयोग किया जाना चाहिए। नाम को {global, Name} रूप में भी दिया जा सकता है, जिस स्थिति में gen_server को global:register_name/2 का उपयोग करके पंजीकृत किया जाता है।

  • दूसरा तर्क, ch3 , कॉलबैक मॉड्यूल का नाम है, अर्थात, वह मॉड्यूल जहां कॉलबैक फ़ंक्शन स्थित हैं।

    इंटरफ़ेस फ़ंक्शंस ( start_link , alloc , और free ) तब कॉलबैक फ़ंक्शंस ( init , handle_call , और handle_cast ) के रूप में एक ही मॉड्यूल में स्थित हैं। यह सामान्य रूप से अच्छा प्रोग्रामिंग अभ्यास है, जिसमें एक मॉड्यूल में निहित एक प्रक्रिया के अनुरूप कोड होता है।

  • तीसरा तर्क, [] , एक शब्द है जिसे कॉलबैक फ़ंक्शन init रूप में पास किया गया है। यहाँ, init को किसी भी indata की आवश्यकता नहीं है और तर्क को अनदेखा करता है।

  • चौथा तर्क, [] , विकल्पों की एक सूची है। उपलब्ध विकल्पों के लिए gen_server(3) मैनुअल पेज देखें।

यदि नाम पंजीकरण सफल होता है, तो नई gen_server प्रक्रिया कॉलबैक फ़ंक्शन ch3:init([]) कॉल करती है। init से {ok, State} लौटने की उम्मीद है, जहां State gen_server की आंतरिक स्थिति है। इस मामले में, राज्य उपलब्ध चैनल है।

init(_Args) ->
    {ok, channels()}.

gen_server:start_link तुल्यकालिक है। यह तब तक वापस नहीं आता है जब तक कि gen_server को प्रारंभ नहीं किया गया है और अनुरोध प्राप्त करने के लिए तैयार है।

gen_server:start_link का उपयोग किया जाना चाहिए यदि gen_server एक पर्यवेक्षण ट्री का हिस्सा है, जो कि एक पर्यवेक्षक द्वारा शुरू किया गया है। एक और कार्य है, gen_server:start , एक स्टैंडअलोन gen_server शुरू करने के लिए, अर्थात, एक gen_server जो पर्यवेक्षण पेड़ का हिस्सा नहीं है।

२.४ समकालिक अनुरोध - कॉल

सिंक्रोनस अनुरोध alloc() gen_server:call/2 का उपयोग करके लागू किया gen_server:call/2 :

alloc() ->
    gen_server:call(ch3, alloc).

ch3 gen_server का नाम है और इसे शुरू करने के लिए उपयोग किए गए नाम से सहमत होना चाहिए। alloc वास्तविक अनुरोध है।

अनुरोध एक संदेश में किया जाता है और gen_server को भेजा जाता है। जब अनुरोध प्राप्त होता है, तो gen_server handle_call(Request, From, State) कॉल करता है, जिसे टपल {reply,Reply,State1} gen_server , gen_server handle_call(Request, From, State) {reply,Reply,State1} वापस करने की उम्मीद है। Reply वह Reply है जो क्लाइंट को वापस भेजा जाना है, और gen_server की स्थिति के लिए एक नया मान है।

handle_call(alloc, _From, Chs) ->
    {Ch, Chs2} = alloc(Chs),
    {reply, Ch, Chs2}.

इस स्थिति में, उत्तर आवंटित चैनल Ch और नया राज्य शेष उपलब्ध चैनल Chs2 का सेट है।

इस प्रकार, कॉल ch3:alloc() आवंटित ch3:alloc() आवंटित चैनल Ch को gen_server और gen_server तब नए अनुरोधों की प्रतीक्षा करता है, अब उपलब्ध चैनलों की एक अद्यतन सूची के साथ।

2.5 अतुल्यकालिक अनुरोध - कास्ट

एसिंक्रोनस अनुरोध free(Ch) gen_server:cast/2 का उपयोग करके कार्यान्वित किया gen_server:cast/2 :

free(Ch) ->
    gen_server:cast(ch3, {free, Ch}).

ch3 gen_server का नाम है। {free, Ch} वास्तविक अनुरोध है।

अनुरोध एक संदेश में किया जाता है और gen_server को भेजा जाता है। cast , और इस तरह free , फिर ok

जब अनुरोध प्राप्त होता है, तो gen_server handle_cast(Request, State) कॉल करता है, जो कि एक टपल {noreply,State1} handle_cast(Request, State) {noreply,State1} वापस आने की उम्मीद है। gen_server की स्थिति के लिए एक नया मान है।

handle_cast({free, Ch}, Chs) ->
    Chs2 = free(Ch, Chs),
    {noreply, Chs2}.

इस स्थिति में, नया राज्य उपलब्ध चैनल Chs2 की अद्यतन सूची है। gen_server अब नए अनुरोधों के लिए तैयार है।

2.6 रोकना

एक पर्यवेक्षण वृक्ष में

यदि gen_server एक पर्यवेक्षण पेड़ का हिस्सा है, तो कोई स्टॉप फ़ंक्शन की आवश्यकता नहीं है। gen_server अपने पर्यवेक्षक द्वारा स्वचालित रूप से समाप्त हो जाता है। वास्तव में यह कैसे किया जाता है यह पर्यवेक्षक में निर्धारित shutdown strategy द्वारा परिभाषित किया गया है।

यदि समाप्ति से पहले सफाई करना आवश्यक है, तो शटडाउन रणनीति का समय-आउट मान होना चाहिए और gen_server में निकास संकेतों को फंसाने के लिए gen_server को सेट करना होगा। जब शटडाउन का आदेश दिया जाता है, तो gen_server कॉलबैक फ़ंक्शन को terminate(shutdown, State) करता terminate(shutdown, State) :

init(Args) ->
    ...,
    process_flag(trap_exit, true),
    ...,
    {ok, State}.

...

terminate(shutdown, State) ->
    ..code for cleaning up here..
    ok.

स्टैंडअलोन Gen_Servers

यदि gen_server पर्यवेक्षण पेड़ का हिस्सा नहीं है, तो एक स्टॉप फ़ंक्शन उपयोगी हो सकता है, उदाहरण के लिए:

...
export([stop/0]).
...

stop() ->
    gen_server:cast(ch3, stop).
...

handle_cast(stop, State) ->
    {stop, normal, State};
handle_cast({free, Ch}, State) ->
    ....

...

terminate(normal, State) ->
    ok.

स्टॉपबैक हैंडल को stop अनुरोध एक टपल {stop,normal,State1} , जहां normal निर्दिष्ट करता है कि यह एक सामान्य टर्मिनेशन है और स्टेट 1 gen_server की स्थिति के लिए एक नया मान है। इसके कारण gen_server को terminate(normal, State1) gen_server terminate(normal, State1) और फिर इसे gen_server terminate(normal, State1) कर दिया जाता है।

2.7 अन्य संदेशों को संभालना

यदि gen_server को अनुरोधों के अलावा अन्य संदेश प्राप्त करने में सक्षम होना है, तो उन्हें संभालने के लिए कॉलबैक फ़ंक्शन handle_info(Info, State) को लागू किया जाना चाहिए। अन्य संदेशों के उदाहरण निकास संदेश हैं, यदि gen_server अन्य प्रक्रियाओं (पर्यवेक्षक की तुलना में) से जुड़ा हुआ है और निकास संकेतों को फंसा रहा है।

handle_info({'EXIT', Pid, Reason}, State) ->
    ..code to handle exits here..
    {noreply, State1}.

code_change पद्धति को भी लागू किया जाना चाहिए।

code_change(OldVsn, State, Extra) ->
    ..code to convert state (and more) during code change
    {ok, NewState}.