<!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() -> 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}.</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() -> gen_server:start_link({local, ch3}, ch3, [], []) => {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) -> {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() -> 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) -> {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) -> 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) -> 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) -> ..., process_flag(trap_exit, true), ..., {ok, State}. ... terminate(shutdown, State) -> ..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() -> gen_server:cast(ch3, stop). ... handle_cast(stop, State) -> {stop, normal, State}; handle_cast({free, Ch}, State) -> .... ... terminate(normal, State) -> 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) -> ..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) -> ..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>