Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 16

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../otp_doc.css" type="text/css">
<title>Erlang -- Gen_Server Behaviour</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="../pdf/otp-system-documentation-5.9.3.1.pdf">PDF</a><br><a href="../index.html">Top</a></small><p><strong>OTP Design Principles</strong><br><strong>User's Guide</strong><br><small>Version 5.9.3.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../js/flipmenu">
<li id="no" title="Overview" expanded="false">Overview<ul>
<li><a href="des_princ.html">
              Top of chapter
            </a></li>
<li title="Supervision Trees"><a href="des_princ.html#id65609">Supervision Trees</a></li>
<li title="Behaviours"><a href="des_princ.html#id59741">Behaviours</a></li>
<li title="Applications"><a href="des_princ.html#id66345">Applications</a></li>
<li title="Releases"><a href="des_princ.html#id61095">Releases</a></li>
<li title="Release Handling"><a href="des_princ.html#id60860">Release Handling</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Gen_Server Behaviour" expanded="true">Gen_Server Behaviour<ul>
<li><a href="gen_server_concepts.html">
              Top of chapter
            </a></li>
<li title="Client-Server Principles"><a href="gen_server_concepts.html#id64192">Client-Server Principles</a></li>
<li title="Example"><a href="gen_server_concepts.html#id61515">Example</a></li>
<li title="Starting a Gen_Server"><a href="gen_server_concepts.html#id67798">Starting a Gen_Server</a></li>
<li title="Synchronous Requests - Call"><a href="gen_server_concepts.html#id66815">Synchronous Requests - Call</a></li>
<li title="Asynchronous Requests - Cast"><a href="gen_server_concepts.html#id62843">Asynchronous Requests - Cast</a></li>
<li title="Stopping"><a href="gen_server_concepts.html#id67345">Stopping</a></li>
<li title="Handling Other Messages"><a href="gen_server_concepts.html#id67435">Handling Other Messages</a></li>
</ul>
</li>
<li id="no" title="Gen_Fsm Behaviour" expanded="false">Gen_Fsm Behaviour<ul>
<li><a href="fsm.html">
              Top of chapter
            </a></li>
<li title="Finite State Machines"><a href="fsm.html#id68991">Finite State Machines</a></li>
<li title="Example"><a href="fsm.html#id69046">Example</a></li>
<li title="Starting a Gen_Fsm"><a href="fsm.html#id69093">Starting a Gen_Fsm</a></li>
<li title="Notifying About Events"><a href="fsm.html#id69273">Notifying About Events</a></li>
<li title="Timeouts"><a href="fsm.html#id69352">Timeouts</a></li>
<li title="All State Events"><a href="fsm.html#id69391">All State Events</a></li>
<li title="Stopping"><a href="fsm.html#id69423">Stopping</a></li>
<li title="Handling Other Messages"><a href="fsm.html#id69514">Handling Other Messages</a></li>
</ul>
</li>
<li id="no" title="Gen_Event Behaviour" expanded="false">Gen_Event Behaviour<ul>
<li><a href="events.html">
              Top of chapter
            </a></li>
<li title="Event Handling Principles"><a href="events.html#id69613">Event Handling Principles</a></li>
<li title="Example"><a href="events.html#id69665">Example</a></li>
<li title="Starting an Event Manager"><a href="events.html#id69706">Starting an Event Manager</a></li>
<li title="Adding an Event Handler"><a href="events.html#id70832">Adding an Event Handler</a></li>
<li title="Notifying About Events"><a href="events.html#id70916">Notifying About Events</a></li>
<li title="Deleting an Event Handler"><a href="events.html#id70987">Deleting an Event Handler</a></li>
<li title="Stopping"><a href="events.html#id71062">Stopping</a></li>
<li title="Handling Other Messages"><a href="events.html#id71116">Handling Other Messages</a></li>
</ul>
</li>
<li id="no" title="Supervisor Behaviour" expanded="false">Supervisor Behaviour<ul>
<li><a href="sup_princ.html">
              Top of chapter
            </a></li>
<li title="Supervision Principles"><a href="sup_princ.html#id71210">Supervision Principles</a></li>
<li title="Example"><a href="sup_princ.html#id71235">Example</a></li>
<li title="Restart Strategy"><a href="sup_princ.html#id71306">Restart Strategy</a></li>
<li title="Maximum Restart Frequency"><a href="sup_princ.html#id71384">Maximum Restart Frequency</a></li>
<li title="Child Specification"><a href="sup_princ.html#id71906">Child Specification</a></li>
<li title="Starting a Supervisor"><a href="sup_princ.html#id72235">Starting a Supervisor</a></li>
<li title="Adding a Child Process"><a href="sup_princ.html#id72349">Adding a Child Process</a></li>
<li title="Stopping a Child Process"><a href="sup_princ.html#id72393">Stopping a Child Process</a></li>
<li title="Simple-One-For-One Supervisors"><a href="sup_princ.html#id72443">Simple-One-For-One Supervisors</a></li>
<li title="Stopping"><a href="sup_princ.html#id72567">Stopping</a></li>
</ul>
</li>
<li id="no" title="Sys and Proc_Lib" expanded="false">Sys and Proc_Lib<ul>
<li><a href="spec_proc.html">
              Top of chapter
            </a></li>
<li title="Simple Debugging"><a href="spec_proc.html#id72665">Simple Debugging</a></li>
<li title="Special Processes"><a href="spec_proc.html#id72749">Special Processes</a></li>
<li title="User-Defined Behaviours"><a href="spec_proc.html#id73359">User-Defined Behaviours</a></li>
</ul>
</li>
<li id="no" title="Applications" expanded="false">Applications<ul>
<li><a href="applications.html">
              Top of chapter
            </a></li>
<li title="Application Concept"><a href="applications.html#id73539">Application Concept</a></li>
<li title="Application Callback Module"><a href="applications.html#id73606">Application Callback Module</a></li>
<li title="Application Resource File"><a href="applications.html#id73720">Application Resource File</a></li>
<li title="Directory Structure"><a href="applications.html#id73969">Directory Structure</a></li>
<li title="Application Controller"><a href="applications.html#id74095">Application Controller</a></li>
<li title="Loading and Unloading Applications"><a href="applications.html#id74128">Loading and Unloading Applications</a></li>
<li title="Starting and Stopping Applications"><a href="applications.html#id74190">Starting and Stopping Applications</a></li>
<li title="Configuring an Application"><a href="applications.html#id74278">Configuring an Application</a></li>
<li title="Application Start Types"><a href="applications.html#id74477">Application Start Types</a></li>
</ul>
</li>
<li id="no" title="Included Applications" expanded="false">Included Applications<ul>
<li><a href="included_applications.html">
              Top of chapter
            </a></li>
<li title="Definition"><a href="included_applications.html#id74617">Definition</a></li>
<li title="Specifying Included Applications"><a href="included_applications.html#id74682">Specifying Included Applications</a></li>
<li title="Synchronizing Processes During Startup"><a href="included_applications.html#id74708">Synchronizing Processes During Startup</a></li>
</ul>
</li>
<li id="no" title="Distributed Applications" expanded="false">Distributed Applications<ul>
<li><a href="distributed_applications.html">
              Top of chapter
            </a></li>
<li title="Definition"><a href="distributed_applications.html#id74921">Definition</a></li>
<li title="Specifying Distributed Applications"><a href="distributed_applications.html#id74957">Specifying Distributed Applications</a></li>
<li title="Starting and Stopping Distributed Applications"><a href="distributed_applications.html#id75164">Starting and Stopping Distributed Applications</a></li>
<li title="Failover"><a href="distributed_applications.html#id75266">Failover</a></li>
<li title="Takeover"><a href="distributed_applications.html#id75408">Takeover</a></li>
</ul>
</li>
<li id="no" title="Releases" expanded="false">Releases<ul>
<li><a href="release_structure.html">
              Top of chapter
            </a></li>
<li title="Release Concept"><a href="release_structure.html#id75603">Release Concept</a></li>
<li title="Release Resource File"><a href="release_structure.html#id75656">Release Resource File</a></li>
<li title="Generating Boot Scripts"><a href="release_structure.html#id75803">Generating Boot Scripts</a></li>
<li title="Creating a Release Package"><a href="release_structure.html#id75897">Creating a Release Package</a></li>
<li title="Directory Structure"><a href="release_structure.html#id76046">Directory Structure</a></li>
</ul>
</li>
<li id="no" title="Release Handling" expanded="false">Release Handling<ul>
<li><a href="release_handling.html">
              Top of chapter
            </a></li>
<li title="Release Handling Principles"><a href="release_handling.html#id76299">Release Handling Principles</a></li>
<li title="Requirements"><a href="release_handling.html#id76543">Requirements</a></li>
<li title="Distributed Systems"><a href="release_handling.html#id76636">Distributed Systems</a></li>
<li title="Release Handling Instructions"><a href="release_handling.html#id76663">Release Handling Instructions</a></li>
<li title="Application Upgrade File"><a href="release_handling.html#id77177">Application Upgrade File</a></li>
<li title="Release Upgrade File"><a href="release_handling.html#id77359">Release Upgrade File</a></li>
<li title="Installing a Release"><a href="release_handling.html#id77515">Installing a Release</a></li>
<li title="Updating Application Specifications"><a href="release_handling.html#id77986">Updating Application Specifications</a></li>
</ul>
</li>
<li id="no" title="Appup Cookbook" expanded="false">Appup Cookbook<ul>
<li><a href="appup_cookbook.html">
              Top of chapter
            </a></li>
<li title="Changing a Functional Module"><a href="appup_cookbook.html#id78170">Changing a Functional Module</a></li>
<li title="Changing a Residence Module"><a href="appup_cookbook.html#id78193">Changing a Residence Module</a></li>
<li title="Changing a Callback Module"><a href="appup_cookbook.html#id78232">Changing a Callback Module</a></li>
<li title="Changing Internal State"><a href="appup_cookbook.html#id78283">Changing Internal State</a></li>
<li title="Module Dependencies"><a href="appup_cookbook.html#id78417">Module Dependencies</a></li>
<li title="Changing Code For a Special Process"><a href="appup_cookbook.html#id78588">Changing Code For a Special Process</a></li>
<li title="Changing a Supervisor"><a href="appup_cookbook.html#id78755">Changing a Supervisor</a></li>
<li title="Adding or Deleting a Module"><a href="appup_cookbook.html#id79000">Adding or Deleting a Module</a></li>
<li title="Starting or Terminating a Process"><a href="appup_cookbook.html#id79026">Starting or Terminating a Process</a></li>
<li title="Adding or Removing an Application"><a href="appup_cookbook.html#id79044">Adding or Removing an Application</a></li>
<li title="Restarting an Application"><a href="appup_cookbook.html#id79075">Restarting an Application</a></li>
<li title="Changing an Application Specification"><a href="appup_cookbook.html#id79117">Changing an Application Specification</a></li>
<li title="Changing Application Configuration"><a href="appup_cookbook.html#id79141">Changing Application Configuration</a></li>
<li title="Changing Included Applications"><a href="appup_cookbook.html#id79174">Changing Included Applications</a></li>
<li title="Changing Non-Erlang Code"><a href="appup_cookbook.html#id79414">Changing Non-Erlang Code</a></li>
<li title="Emulator Restart and Upgrade"><a href="appup_cookbook.html#id79499">Emulator Restart and Upgrade</a></li>
<li title="Emulator Upgrade from pre OTP R15"><a href="appup_cookbook.html#id79575">Emulator Upgrade from pre OTP R15</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>2 Gen_Server Behaviour</h1>
  
  <a name="gen_server"></a>
  <p>This chapter should be read in conjunction with
    <span class="bold_code"><a href="javascript:erlhref('../../','stdlib','gen_server.html');">gen_server(3)</a></span>,
    where all interface functions and callback
    functions are described in detail.</p>

  <h3><a name="id64192">2.1 
        Client-Server Principles</a></h3>
    
    <p>The client-server model is characterized by a central server
      and an arbitrary number of clients. The client-server model is
      generally used for resource management operations, where several
      different clients want to share a common resource. The server is
      responsible for managing this resource.</p>
    <a name="clientserver"></a>
    <img alt="IMAGE MISSING" src="../design_principles/clientserver.gif"><br>
      <em>Figure
        2.1:
         
        Client-Server Model</em>
    
  

  <h3><a name="id61515">2.2 
        Example</a></h3>
    
    <p>An example of a simple server written in plain Erlang was
      given in <span class="bold_code"><a href="des_princ.html#ch1">Overview</a></span>.
      The server can be re-implemented using <span class="code">gen_server</span>,
      resulting in this callback module:</p>
    <a name="ex"></a>
    <div class="example"><pre>
-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() -&gt;
    gen_server:start_link({local, ch3}, ch3, [], []).

alloc() -&gt;
    gen_server:call(ch3, alloc).

free(Ch) -&gt;
    gen_server:cast(ch3, {free, Ch}).

init(_Args) -&gt;
    {ok, channels()}.

handle_call(alloc, _From, Chs) -&gt;
    {Ch, Chs2} = alloc(Chs),
    {reply, Ch, Chs2}.

handle_cast({free, Ch}, Chs) -&gt;
    Chs2 = free(Ch, Chs),
    {noreply, Chs2}.</pre></div>
    <p>The code is explained in the next sections.</p>
  

  <h3><a name="id67798">2.3 
        Starting a Gen_Server</a></h3>
    
    <p>In the example in the previous section, the gen_server is started
      by calling <span class="code">ch3:start_link()</span>:</p>
    <div class="example"><pre>
start_link() -&gt;
    gen_server:start_link({local, ch3}, ch3, [], []) =&gt; {ok, Pid}</pre></div>
    <p><span class="code">start_link</span> calls the function
      <span class="code">gen_server:start_link/4</span>. This function spawns and links to
      a new process, a gen_server.</p>
    <ul>
      <li>
        <p>The first argument <span class="code">{local, ch3}</span> specifies the name. In
          this case, the gen_server will be locally registered as
          <span class="code">ch3</span>.</p>
        <p>If the name is omitted, the gen_server is not registered.
          Instead its pid must be used. The name could also be given
          as <span class="code">{global, Name}</span>, in which case the gen_server is
          registered using <span class="code">global:register_name/2</span>.</p>
      </li>
      <li>
        <p>The second argument, <span class="code">ch3</span>, is the name of the callback
          module, that is the module where the callback functions are
          located.</p>
        <p>In this case, the interface functions (<span class="code">start_link</span>,
          <span class="code">alloc</span> and <span class="code">free</span>) are located in the same module
          as the callback functions (<span class="code">init</span>, <span class="code">handle_call</span> and
          <span class="code">handle_cast</span>). This is normally good programming
          practice, to have the code corresponding to one process
          contained in one module.</p>
      </li>
      <li>
        <p>The third argument, [], is a term which is passed as-is to
          the callback function <span class="code">init</span>. Here, <span class="code">init</span> does not
          need any indata and ignores the argument.</p>
      </li>
      <li>
        <p>The fourth argument, [], is a list of options. See
          <span class="code">gen_server(3)</span> for available options.</p>
      </li>
    </ul>
    <p>If name registration succeeds, the new gen_server process calls
      the callback function <span class="code">ch3:init([])</span>. <span class="code">init</span> is expected
      to return <span class="code">{ok, State}</span>, where <span class="code">State</span> is the internal
      state of the gen_server. In this case, the state is the available
      channels.</p>
    <div class="example"><pre>
init(_Args) -&gt;
    {ok, channels()}.</pre></div>
    <p>Note that <span class="code">gen_server:start_link</span> is synchronous. It does
      not return until the gen_server has been initialized and is ready
      to receive requests.</p>
    <p><span class="code">gen_server:start_link</span> must be used if the gen_server is
      part of a supervision tree, i.e. is started by a supervisor.
      There is another function <span class="code">gen_server:start</span> to start a
      stand-alone gen_server, i.e. a gen_server which is not part of a
      supervision tree.</p>
  

  <h3><a name="id66815">2.4 
        Synchronous Requests - Call</a></h3>
    
    <p>The synchronous request <span class="code">alloc()</span> is implemented using
      <span class="code">gen_server:call/2</span>:</p>
    <div class="example"><pre>
alloc() -&gt;
    gen_server:call(ch3, alloc).</pre></div>
    <p><span class="code">ch3</span> is the name of the gen_server and must agree with
      the name used to start it. <span class="code">alloc</span> is the actual request.</p>
    <p>The request is made into a message and sent to the gen_server.
      When the request is received, the gen_server calls
      <span class="code">handle_call(Request, From, State)</span> which is expected to
      return a tuple <span class="code">{reply, Reply, State1}</span>. <span class="code">Reply</span> is
      the reply which should be sent back to the client, and
      <span class="code">State1</span> is a new value for the state of the gen_server.</p>
    <div class="example"><pre>
handle_call(alloc, _From, Chs) -&gt;
    {Ch, Chs2} = alloc(Chs),
    {reply, Ch, Chs2}.</pre></div>
    <p>In this case, the reply is the allocated channel <span class="code">Ch</span> and
      the new state is the set of remaining available channels
      <span class="code">Chs2</span>.</p>
    <p>Thus, the call <span class="code">ch3:alloc()</span> returns the allocated channel
      <span class="code">Ch</span> and the gen_server then waits for new requests, now
      with an updated list of available channels.</p>
  

  <h3><a name="id62843">2.5 
        Asynchronous Requests - Cast</a></h3>
    
    <p>The asynchronous request <span class="code">free(Ch)</span> is implemented using
      <span class="code">gen_server:cast/2</span>:</p>
    <div class="example"><pre>
free(Ch) -&gt;
    gen_server:cast(ch3, {free, Ch}).</pre></div>
    <p><span class="code">ch3</span> is the name of the gen_server. <span class="code">{free, Ch}</span> is
      the actual request.</p>
    <p>The request is made into a message and sent to the gen_server.
      <span class="code">cast</span>, and thus <span class="code">free</span>, then returns <span class="code">ok</span>.</p>
    <p>When the request is received, the gen_server calls
      <span class="code">handle_cast(Request, State)</span> which is expected to
      return a tuple <span class="code">{noreply, State1}</span>. <span class="code">State1</span> is a new
      value for the state of the gen_server.</p>
    <div class="example"><pre>
handle_cast({free, Ch}, Chs) -&gt;
    Chs2 = free(Ch, Chs),
    {noreply, Chs2}.</pre></div>
    <p>In this case, the new state is the updated list of available
      channels <span class="code">Chs2</span>. The gen_server is now ready for new
      requests.</p>
  

  <h3><a name="id67345">2.6 
        Stopping</a></h3>
    

    <h4>In a Supervision Tree</h4>
      
      <p>If the gen_server is part of a supervision tree, no stop
        function is needed. The gen_server will automatically be
        terminated by its supervisor. Exactly how this is done is
        defined by a <span class="bold_code"><a href="sup_princ.html#shutdown">shutdown strategy</a></span> set in the supervisor.</p>
      <p>If it is necessary to clean up before termination, the shutdown
        strategy must be a timeout value and the gen_server must be set
        to trap exit signals in the <span class="code">init</span> function. When ordered
        to shutdown, the gen_server will then call the callback function
        <span class="code">terminate(shutdown, State)</span>:</p>
      <div class="example"><pre>
init(Args) -&gt;
    ...,
    process_flag(trap_exit, true),
    ...,
    {ok, State}.

...

terminate(shutdown, State) -&gt;
    ..code for cleaning up here..
    ok.</pre></div>
    

    <h4>Stand-Alone Gen_Servers</h4>
      
      <p>If the gen_server is not part of a supervision tree, a stop
        function may be useful, for example:</p>
      <div class="example"><pre>
...
export([stop/0]).
...

stop() -&gt;
    gen_server:cast(ch3, stop).
...

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

...

terminate(normal, State) -&gt;
    ok.</pre></div>
      <p>The callback function handling the <span class="code">stop</span> request returns
        a tuple <span class="code">{stop, normal, State1}</span>, where <span class="code">normal</span>
        specifies that it is a normal termination and <span class="code">State1</span> is
        a new value for the state of the gen_server. This will cause
        the gen_server to call <span class="code">terminate(normal,State1)</span> and then
        terminate gracefully.</p>
    
  

  <h3><a name="id67435">2.7 
        Handling Other Messages</a></h3>
    
    <p>If the gen_server should be able to receive other messages than
      requests, the callback function <span class="code">handle_info(Info, State)</span>
      must be implemented to handle them. Examples of other messages
      are exit messages, if the gen_server is linked to other processes
      (than the supervisor) and trapping exit signals.</p>
    <div class="example"><pre>
handle_info({'EXIT', Pid, Reason}, State) -&gt;
    ..code to handle exits here..
    {noreply, State1}.</pre></div>
    <p>The code_change method also has to be implemented.</p>
    <div class="example"><pre>
code_change(OldVsn, State, Extra) -&gt;
    ..code to convert state (and more) during code change
    {ok, NewState}.</pre></div>
  
</div>
<div class="footer">
<hr>
<p>Copyright © 1997-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>