diff options
Diffstat (limited to 'system/doc/design_principles/gen_server_concepts.xml')
-rw-r--r-- | system/doc/design_principles/gen_server_concepts.xml | 160 |
1 files changed, 83 insertions, 77 deletions
diff --git a/system/doc/design_principles/gen_server_concepts.xml b/system/doc/design_principles/gen_server_concepts.xml index d24d87aa03..d721845c6d 100644 --- a/system/doc/design_principles/gen_server_concepts.xml +++ b/system/doc/design_principles/gen_server_concepts.xml @@ -21,7 +21,7 @@ </legalnotice> - <title>Gen_Server Behaviour</title> + <title>gen_server Behaviour</title> <prepared></prepared> <docno></docno> <date></date> @@ -29,16 +29,16 @@ <file>gen_server_concepts.xml</file> </header> <marker id="gen_server"></marker> - <p>This chapter should be read in conjunction with - <seealso marker="stdlib:gen_server">gen_server(3)</seealso>, - where all interface functions and callback - functions are described in detail.</p> + <p>This section is to be read with the + <seealso marker="stdlib:gen_server">gen_server(3)</seealso> + manual page in <c>stdblib</c>, where all interface functions and + callback functions are described in detail.</p> <section> <title>Client-Server Principles</title> <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 + used for resource management operations, where several different clients want to share a common resource. The server is responsible for managing this resource.</p> <marker id="clientserver"></marker> @@ -49,9 +49,10 @@ <section> <title>Example</title> - <p>An example of a simple server written in plain Erlang was - given in <seealso marker="des_princ#ch1">Overview</seealso>. - The server can be re-implemented using <c>gen_server</c>, + <p>An example of a simple server written in plain Erlang is + provided in + <seealso marker="des_princ#ch1">Overview</seealso>. + The server can be reimplemented using <c>gen_server</c>, resulting in this callback module:</p> <marker id="ex"></marker> <code type="none"> @@ -86,61 +87,60 @@ handle_cast({free, Ch}, Chs) -> <section> <title>Starting a Gen_Server</title> - <p>In the example in the previous section, the gen_server is started - by calling <c>ch3:start_link()</c>:</p> + <p>In the example in the previous section, <c>gen_server</c> is + started by calling <c>ch3:start_link()</c>:</p> <code type="none"> start_link() -> gen_server:start_link({local, ch3}, ch3, [], []) => {ok, Pid}</code> - <p><c>start_link</c> calls the function - <c>gen_server:start_link/4</c>. This function spawns and links to - a new process, a gen_server.</p> + <p><c>start_link</c> calls function <c>gen_server:start_link/4</c>. + This function spawns and links to a new process, a + <c>gen_server</c>.</p> <list type="bulleted"> <item> - <p>The first argument <c>{local, ch3}</c> specifies the name. In - this case, the gen_server will be locally registered as - <c>ch3</c>.</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 <c>{global, Name}</c>, in which case the gen_server is + <p>The first argument, <c>{local, ch3}</c>, specifies the name. + The gen_server is then locally registered as <c>ch3</c>.</p> + <p>If the name is omitted, the <c>gen_server</c> is not registered. + Instead its pid must be used. The name can also be given + as <c>{global, Name}</c>, in which case the <c>gen_server</c> is registered using <c>global:register_name/2</c>.</p> </item> <item> <p>The second argument, <c>ch3</c>, is the name of the callback - module, that is the module where the callback functions are + module, that is, the module where the callback functions are located.</p> - <p>In this case, the interface functions (<c>start_link</c>, - <c>alloc</c> and <c>free</c>) are located in the same module - as the callback functions (<c>init</c>, <c>handle_call</c> and + <p>The interface functions (<c>start_link</c>, <c>alloc</c>, + and <c>free</c>) are then located in the same module + as the callback functions (<c>init</c>, <c>handle_call</c>, and <c>handle_cast</c>). This is normally good programming practice, to have the code corresponding to one process contained in one module.</p> </item> <item> - <p>The third argument, [], is a term which is passed as-is to - the callback function <c>init</c>. Here, <c>init</c> does not + <p>The third argument, <c>[]</c>, is a term that is passed as is + to the callback function <c>init</c>. Here, <c>init</c> does not need any indata and ignores the argument.</p> </item> <item> - <p>The fourth argument, [], is a list of options. See - <c>gen_server(3)</c> for available options.</p> + <p>The fourth argument, <c>[]</c>, is a list of options. See the + <c>gen_server(3)</c> manual page for available options.</p> </item> </list> - <p>If name registration succeeds, the new gen_server process calls - the callback function <c>ch3:init([])</c>. <c>init</c> is expected - to return <c>{ok, State}</c>, where <c>State</c> is the internal - state of the gen_server. In this case, the state is the available - channels.</p> + <p>If name registration succeeds, the new <c>gen_server</c> process + calls the callback function <c>ch3:init([])</c>. <c>init</c> is + expected to return <c>{ok, State}</c>, where <c>State</c> is the + internal state of the <c>gen_server</c>. In this case, the state + is the available channels.</p> <code type="none"> init(_Args) -> {ok, channels()}.</code> - <p>Note that <c>gen_server:start_link</c> is synchronous. It does - not return until the gen_server has been initialized and is ready + <p><c>gen_server:start_link</c> is synchronous. It does not return + until the <c>gen_server</c> has been initialized and is ready to receive requests.</p> - <p><c>gen_server:start_link</c> must be used if the gen_server is - part of a supervision tree, i.e. is started by a supervisor. - There is another function <c>gen_server:start</c> to start a - stand-alone gen_server, i.e. a gen_server which is not part of a - supervision tree.</p> + <p><c>gen_server:start_link</c> must be used if the <c>gen_server</c> + is part of a supervision tree, that is, started by a supervisor. + There is another function, <c>gen_server:start</c>, to start a + standalone <c>gen_server</c>, that is, a <c>gen_server</c> that + is not part of a supervision tree.</p> </section> <section> @@ -150,14 +150,17 @@ init(_Args) -> <code type="none"> alloc() -> gen_server:call(ch3, alloc).</code> - <p><c>ch3</c> is the name of the gen_server and must agree with - the name used to start it. <c>alloc</c> 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 - <c>handle_call(Request, From, State)</c> which is expected to - return a tuple <c>{reply, Reply, State1}</c>. <c>Reply</c> is - the reply which should be sent back to the client, and - <c>State1</c> is a new value for the state of the gen_server.</p> + <p><c>ch3</c> is the name of the <c>gen_server</c> and must agree + with the name used to start it. <c>alloc</c> is the actual + request.</p> + <p>The request is made into a message and sent to the + <c>gen_server</c>. When the request is received, the + <c>gen_server</c> calls + <c>handle_call(Request, From, State)</c>, which is expected to + return a tuple <c>{reply,Reply,State1}</c>. <c>Reply</c> is + the reply that is to be sent back to the client, and + <c>State1</c> is a new value for the state of the + <c>gen_server</c>.</p> <code type="none"> handle_call(alloc, _From, Chs) -> {Ch, Chs2} = alloc(Chs), @@ -166,8 +169,8 @@ handle_call(alloc, _From, Chs) -> the new state is the set of remaining available channels <c>Chs2</c>.</p> <p>Thus, the call <c>ch3:alloc()</c> returns the allocated channel - <c>Ch</c> and the gen_server then waits for new requests, now - with an updated list of available channels.</p> + <c>Ch</c> and the <c>gen_server</c> then waits for new requests, + now with an updated list of available channels.</p> </section> <section> @@ -177,20 +180,21 @@ handle_call(alloc, _From, Chs) -> <code type="none"> free(Ch) -> gen_server:cast(ch3, {free, Ch}).</code> - <p><c>ch3</c> is the name of the gen_server. <c>{free, Ch}</c> is - the actual request.</p> - <p>The request is made into a message and sent to the gen_server. + <p><c>ch3</c> is the name of the <c>gen_server</c>. + <c>{free, Ch}</c> is the actual request.</p> + <p>The request is made into a message and sent to the + <c>gen_server</c>. <c>cast</c>, and thus <c>free</c>, then returns <c>ok</c>.</p> - <p>When the request is received, the gen_server calls - <c>handle_cast(Request, State)</c> which is expected to - return a tuple <c>{noreply, State1}</c>. <c>State1</c> is a new - value for the state of the gen_server.</p> + <p>When the request is received, the <c>gen_server</c> calls + <c>handle_cast(Request, State)</c>, which is expected to + return a tuple <c>{noreply,State1}</c>. <c>State1</c> is a new + value for the state of the <c>gen_server</c>.</p> <code type="none"> handle_cast({free, Ch}, Chs) -> Chs2 = free(Ch, Chs), {noreply, Chs2}.</code> <p>In this case, the new state is the updated list of available - channels <c>Chs2</c>. The gen_server is now ready for new + channels <c>Chs2</c>. The <c>gen_server</c> is now ready for new requests.</p> </section> @@ -199,15 +203,17 @@ handle_cast({free, Ch}, Chs) -> <section> <title>In a Supervision Tree</title> - <p>If the gen_server is part of a supervision tree, no stop - function is needed. The gen_server will automatically be + <p>If the <c>gen_server</c> is part of a supervision tree, no stop + function is needed. The <c>gen_server</c> is automatically terminated by its supervisor. Exactly how this is done is - defined by a <seealso marker="sup_princ#shutdown">shutdown strategy</seealso> set in the supervisor.</p> + defined by a + <seealso marker="sup_princ#shutdown">shutdown strategy</seealso> + 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 <c>init</c> function. When ordered - to shutdown, the gen_server will then call the callback function - <c>terminate(shutdown, State)</c>:</p> + strategy must be a time-out value and the <c>gen_server</c> must + be set to trap exit signals in function <c>init</c>. When ordered + to shutdown, the <c>gen_server</c> then calls the callback + function <c>terminate(shutdown, State)</c>:</p> <code type="none"> init(Args) -> ..., @@ -223,9 +229,9 @@ terminate(shutdown, State) -> </section> <section> - <title>Stand-Alone Gen_Servers</title> - <p>If the gen_server is not part of a supervision tree, a stop - function may be useful, for example:</p> + <title>Standalone Gen_Servers</title> + <p>If the <c>gen_server</c> is not part of a supervision tree, a + stop function can be useful, for example:</p> <code type="none"> ... export([stop/0]). @@ -245,26 +251,26 @@ handle_cast({free, Ch}, State) -> terminate(normal, State) -> ok.</code> <p>The callback function handling the <c>stop</c> request returns - a tuple <c>{stop, normal, State1}</c>, where <c>normal</c> + a tuple <c>{stop,normal,State1}</c>, where <c>normal</c> specifies that it is a normal termination and <c>State1</c> is - a new value for the state of the gen_server. This will cause - the gen_server to call <c>terminate(normal,State1)</c> and then - terminate gracefully.</p> + a new value for the state of the <c>gen_server</c>. This causes + the <c>gen_server</c> to call <c>terminate(normal, State1)</c> + and then it terminates gracefully.</p> </section> </section> <section> <title>Handling Other Messages</title> - <p>If the gen_server should be able to receive other messages than - requests, the callback function <c>handle_info(Info, State)</c> + <p>If the <c>gen_server</c> is to be able to receive other messages + than requests, the callback function <c>handle_info(Info, State)</c> 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> + are exit messages, if the <c>gen_server</c> is linked to other + processes (than the supervisor) and trapping exit signals.</p> <code type="none"> handle_info({'EXIT', Pid, Reason}, State) -> ..code to handle exits here.. {noreply, State1}.</code> - <p>The code_change method also has to be implemented.</p> + <p>The <c>code_change</c> method must also be implemented.</p> <code type="none"> code_change(OldVsn, State, Extra) -> ..code to convert state (and more) during code change |