diff options
Diffstat (limited to 'lib/stdlib/doc/src/gen_server.xml')
-rw-r--r-- | lib/stdlib/doc/src/gen_server.xml | 2020 |
1 files changed, 1472 insertions, 548 deletions
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index c0c806c309..4948418b3d 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2021</year> + <year>1996</year><year>2022</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -109,632 +109,1379 @@ gen_server:abcast -----> Module:handle_cast/2 </description> + + + <datatypes> + <datatype> + <name name="server_name"/> + <desc> + <p> + Name specification to use when starting a <c>gen_server</c>. + See functions + <seemfa marker="#start/3"><c>start/3,4</c></seemfa>, + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>, + <seemfa marker="#start_monitor/3"><c>start_monitor/3,4</c></seemfa>, + <seemfa marker="#enter_loop/3"><c>enter_loop/3,4,5</c></seemfa>, + and the type + <seetype marker="#server_ref"><c>server_ref()</c></seetype> + below. + </p> + <taglist> + <tag><c>{local,<anno>LocalName</anno>}</c></tag> + <item> + <p> + Register the <c>gen_server</c> locally + as <c><anno>LocalName</anno></c> using + <seemfa marker="erts:erlang#register/2"> + <c>register/2</c></seemfa>. + </p> + </item> + <tag><c>{global,<anno>GlobalName</anno>}</c></tag> + <item> + <p> + Register the <c>gen_server</c> process id + globally as <c>GlobalName</c> using + <seemfa marker="kernel:global#register_name/2"> + <c>global:register_name/2</c></seemfa>. + </p> + </item> + <tag><c>{via,<anno>RegMod</anno>,<anno>ViaName</anno>}</c></tag> + <item> + <p> + Register the <c>gen_server</c> process with the registry + represented by <c><anno>RegMod</anno></c>. + The <c><anno>RegMod</anno></c> callback is to export + the functions <c>register_name/2</c>, <c>unregister_name/1</c>, + <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave + like the corresponding functions in + <seeerl marker="kernel:global"><c>global</c></seeerl>. + Thus, <c>{via,global,<anno>GlobalName</anno>}</c> + is a valid reference equivalent to + <c>{global,<anno>GlobalName</anno>}</c>. + </p> + </item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="server_ref"/> + <desc> + <p> + Server specification to use when addressing + a <c>gen_server</c>. + See <seemfa marker="#call/2"><c>call/2,3</c></seemfa>, + <seemfa marker="#cast/2"><c>cast/2</c></seemfa>, + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>, + <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>, + <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>, + <seemfa marker="#stop/1"><c>stop/2,3</c></seemfa> + and the type + <seetype marker="#server_name"><c>server_name()</c></seetype> + above. + </p> + <p>It can be:</p> + <taglist> + <tag><c>pid()</c></tag> + <item> + <p> + The <c>gen_server</c>'s process identifier. + </p> + </item> + <tag><c><anno>LocalName</anno></c></tag> + <item> + <p> + The <c>gen_server</c> is locally registered + as <c><anno>LocalName</anno></c> with + <seemfa marker="erts:erlang#register/2"> + <c>register/2</c></seemfa>. + </p> + </item> + <tag><c>{<anno>Name</anno>,<anno>Node</anno>}</c></tag> + <item> + <p> + The <c>gen_server</c> is locally registered + on another node. + </p> + </item> + <tag><c>{global,<anno>GlobalName</anno>}</c></tag> + <item> + <p> + The <c>gen_server</c> is globally registered in + <seeerl marker="kernel:global"><c>global</c></seeerl>. + </p> + </item> + <tag><c>{via,<anno>RegMod</anno>,<anno>ViaName</anno>}</c></tag> + <item> + <p> + The <c>gen_server</c> is registered in + an alternative process registry. + The registry callback module <c><anno>RegMod</anno></c> + is to export functions + <c>register_name/2</c>, <c>unregister_name/1</c>, + <c>whereis_name/1</c>, and <c>send/2</c>, + which are to behave like the corresponding functions in + <seeerl marker="kernel:global"><c>global</c></seeerl>. + Thus, <c>{via,global,<anno>GlobalName</anno>}</c> + is the same as <c>{global,<anno>GlobalName</anno>}</c>. + </p> + </item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="start_opt"/> + <desc> + <p> + Options that can be used when starting + a <c>gen_server</c> server through, for example, + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>. + </p> + <taglist> + <tag><c>{timeout,<anno>Timeout</anno>}</c></tag> + <item> + <p> + How many milliseconds the <c>gen_server</c> process is allowed + to spend initializing or it is terminated and the + start function returns <c>{error,timeout}</c>. + </p> + </item> + <tag> + <c>{spawn_opt,<anno>SpawnOptions</anno>}</c> + </tag> + <item> + <p> + The <c><anno>SpawnOptions</anno></c> option list + is passed to the function used to spawn + the <c>gen_server</c>; see + <seemfa marker="erts:erlang#spawn_opt/2"> + <c>spawn_opt/2</c></seemfa>. + </p> + <note> + <p> + Using spawn option <c>monitor</c> is not + allowed, it causes a <c>badarg</c> failure. + </p> + </note> + </item> + <tag><c>enter_loop_opt()</c></tag> + <item> + <p> + See the type + <seetype marker="#enter_loop_opt"><c>enter_loop_opt()</c></seetype> + below for more start options that are also allowed by + <seemfa marker="#enter_loop/3"><c>enter_loop/3,4,5</c></seemfa>. + </p> + </item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="enter_loop_opt"/> + <desc> + <p> + Options that can be used when starting + a <c>gen_server</c> server through + <seemfa marker="#enter_loop/3"><c>enter_loop/3-5</c></seemfa> + or the start functions such as + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>. + </p> + <taglist> + <tag><c>{hibernate_after,<anno>HibernateAfterTimeout</anno>}</c></tag> + <item> + <p> + Specifies that the <c>gen_server</c> process awaits + any message for <c>HibernateAfterTimeout</c> milliseconds and + if no message is received, the process goes into hibernation + automatically (by calling + <seemfa marker="proc_lib#hibernate/3"> + <c>proc_lib:hibernate/3</c></seemfa>). + </p> + </item> + <tag><c>{debug,<anno>Dbgs</anno>}</c></tag> + <item> + <p> + For every entry in <c><anno>Dbgs</anno></c>, + the corresponding function in + <seeerl marker="sys"><c>sys(3)</c></seeerl> is called. + </p> + </item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="start_ret"/> + <desc> + <p> + Return value from the + <seemfa marker="#start/3"><c>start/3,4</c></seemfa> + and + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa> + functions. + </p> + <taglist> + <tag><c>{ok,<anno>Pid</anno>}</c></tag> + <item> + <p> + The <c>gen_server</c> process was succesfully created + and initialized, with the process identifier + <c><anno>Pid</anno></c>. + </p> + </item> + <tag><c>{error,{already_started,OtherPid}}</c></tag> + <item> + <p> + A process with the specified <c>ServerName</c> exists already + with the process identifier <c>OtherPid</c>. + This <c>gen_server</c> was not started. + </p> + </item> + <tag><c>ignore</c></tag> + <item> + <p> + <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa> + returned <c>ignore</c>, the <c>gen_server</c> process + is terminated. An exit signal <c>normal</c> is sent + to linked processes and ports. + </p> + </item> + <tag><c>{error,<anno>Reason</anno>}</c></tag> + <item> + <p> + <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa> + returned <c>{stop,<anno>Reason</anno>}</c> + or failed with <c><anno>Reason</anno></c>. + The <c>gen_server</c> process is terminated and + an exit signal with the same <c><anno>Reason</anno></c> + is sent to linked processes and ports. + </p> + </item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="start_mon_ret"/> + <desc> + <p> + Return value from the + <seemfa marker="#start_monitor/3"><c>start_monitor/3,4</c></seemfa> + functions. + The same as type + <seetype marker="#start_ret"><c>start_ret()</c></seetype> + except that for a succesful start it returns both + the process identifier <c><anno>Pid</anno></c> and a + <seemfa marker="erts:erlang#monitor/2"><c>monitor/2,3</c></seemfa> + <c>reference()</c> <c><anno>MonRef</anno></c>. + </p> + </desc> + </datatype> + + <datatype> + <name name="from"/> + <desc> + <p> + Destination, given to the <c>gen_server</c> + as the first argument to the callback function + <seemfa marker="#Module:handle_call/3"><c>Module:handle_call/3</c></seemfa>, + to be used by the when replying through + <seemfa marker="#reply/2"><c>reply/2</c></seemfa> + (instead of through the callback function's return value) + to the process <c><anno>Client</anno></c> + that has called the <c>gen_server</c> using + <seemfa marker="#call/2"><c>call/2,3</c></seemfa>. + <c><anno>Tag</anno></c> is a term that is unique + for this call/request instance. + </p> + </desc> + </datatype> + + <datatype> + <name name="reply_tag"/> + <desc> + <p> + A handle that associates a reply to the corresponding request. + </p> + </desc> + </datatype> + + <datatype> + <name name="request_id"/> + <desc> + <p> + An opaque request identifier. See + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> + for details. + </p> + </desc> + </datatype> + + <datatype> + <name name="request_id_collection"/> + <desc> + <p> + An opaque collection of request identifiers + (<seetype marker="#request_id"><c>request_id()</c></seetype>) + where each request identifier can be associated with a label + chosen by the user. For more information see + <seemfa marker="#reqids_new/0"><c>reqids_new/0</c></seemfa>. + </p> + </desc> + </datatype> + + <datatype> + <name name="response_timeout"/> + <desc> + <p> + Used to set a time limit on how long to wait for a response using + either + <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>, + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>, + <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>, + or + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>. + The time unit used is <c>millisecond</c>. Currently valid values: + </p> + <taglist> + <tag><c>0..4294967295</c></tag> + <item><p> + Timeout relative to current time in milliseconds. + </p></item> + <tag><c>infinity</c></tag> + <item><p> + Infinite timeout. That is, the operation will never time out. + </p></item> + <tag><c>{abs, Timeout}</c></tag> + <item><p> + An absolute + <seemfa marker="erts:erlang#monotonic_time/1">Erlang monotonic time</seemfa> + timeout in milliseconds. That is, the operation will time out when + <seemfa marker="erts:erlang#monotonic_time/1"><c>erlang:monotonic_time(millisecond)</c></seemfa> + returns a value larger than or equal to <c>Timeout</c>. <c>Timeout</c> + is not allowed to identify a time further into the future than <c>4294967295</c> + milliseconds. Identifying the timeout using an absolute timeout value + is especially handy when you have a deadline for responses corresponding + to a complete collection of requests + (<seetype marker="#request_id_collection"><c>request_id_collection()</c></seetype>) +, + since you do not have to recalculate the relative time until the deadline + over and over again. + </p></item> + </taglist> + </desc> + </datatype> + + <datatype> + <name name="format_status"/> + <desc> + <p> + A map that describes the <c>gen_server</c> status. + The keys are: + </p> + <taglist> + <tag><c>state</c></tag> + <item>The internal state of the <c>gen_server</c> process.</item> + <tag><c>message</c></tag> + <item>The message that caused the server to terminate.</item> + <tag><c>reason</c></tag> + <item>The reason that caused the server to terminate.</item> + <tag><c>log</c></tag> + <item> + The <seemfa marker="sys#log/2">sys log</seemfa> of the server. + </item> + </taglist> + <p> + New associations may be added to the status map + without prior notice. + </p> + </desc> + </datatype> + </datatypes> + + + <funcs> <func> - <name since="">abcast(Name, Request) -> abcast</name> - <name since="">abcast(Nodes, Name, Request) -> abcast</name> - <fsummary>Send an asynchronous request to many generic servers.</fsummary> - <type> - <v>Nodes = [Node]</v> - <v> Node = atom()</v> - <v>Name = atom()</v> - <v>Request = term()</v> - </type> + <name name="abcast" arity="2" since=""/> + <name name="abcast" arity="3" since=""/> + <fsummary> + Send an asynchronous request to many generic servers. + </fsummary> <desc> - <p>Sends an asynchronous request to the <c>gen_server</c> processes - locally registered as <c>Name</c> at the specified nodes. The function + <p> + Sends an asynchronous request to the <c>gen_server</c> processes + locally registered as <c><anno>Name</anno></c> + at the specified nodes. The function returns immediately and ignores nodes that do not exist, or - where the <c>gen_server</c> <c>Name</c> does not exist. + where the <c>gen_server</c> + <c><anno>Name</anno></c> does not exist. The <c>gen_server</c> processes call <seemfa marker="#Module:handle_cast/2"> - <c>Module:handle_cast/2</c></seemfa> to handle the request.</p> - <p>For a description of the arguments, see - <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>.</p> + <c>Module:handle_cast/2</c> + </seemfa> to handle the request. + </p> + <p> + For a description of the arguments, see + <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>. + </p> </desc> </func> <func> - <name since="">call(ServerRef, Request) -> Reply</name> - <name since="">call(ServerRef, Request, Timeout) -> Reply</name> + <name name="call" arity="2" since=""/> + <name name="call" arity="3" since=""/> <fsummary>Make a synchronous call to a generic server.</fsummary> - <type> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Request = term()</v> - <v>Timeout = int()>0 | infinity</v> - <v>Reply = term()</v> - </type> <desc> - <p>Makes a synchronous call to the <c>ServerRef</c> of the - <c>gen_server</c> process + <p> + Makes a synchronous call to the + <c><anno>ServerRef</anno></c> of the <c>gen_server</c> process by sending a request and waiting until a reply arrives or a time-out occurs. The <c>gen_server</c> process calls <seemfa marker="#Module:handle_call/3"> - <c>Module:handle_call/3</c></seemfa> to handle the request.</p> - <p><c>ServerRef</c> can be any of the following:</p> - <list type="bulleted"> - <item>The pid</item> - <item><c>Name</c>, if the <c>gen_server</c> process is locally - registered</item> - <item><c>{Name,Node}</c>, if the <c>gen_server</c> process is locally - registered at another node</item> - <item><c>{global,GlobalName}</c>, if the <c>gen_server</c> process is - globally registered</item> - <item><c>{via,Module,ViaName}</c>, if the <c>gen_server</c> process is - registered through an alternative process registry</item> - </list> - <p><c>Request</c> is any term that is passed as the - first argument to <c>Module:handle_call/3</c>.</p> - <p><c>Timeout</c> is an integer greater than zero that + <c>Module:handle_call/3</c> + </seemfa> + to handle the request. + </p> + <p> + See also <c><anno>ServerRef</anno></c>'s type + <seetype marker="#server_ref"><c>server_ref()</c></seetype>. + </p> + <p> + <c><anno>Request</anno></c> is any term that is passed as the + first argument to <c>Module:handle_call/3</c>. + </p> + <p> + <c><anno>Timeout</anno></c> is an integer that specifies how many milliseconds to wait for a reply, or - the atom <c>infinity</c> to wait indefinitely. Defaults to - 5000. If no reply is received within the specified time, - the function call fails. If the caller catches the failure - and continues running, and the server is just late with the reply, - it can arrive at any time later into the message queue of the caller. - The caller must in this case be prepared for this - and discard any such garbage messages that are two element - tuples with a reference as the first element.</p> - <p>The return value <c>Reply</c> is defined in the return value - of <c>Module:handle_call/3</c>.</p> - <p>The call can fail for many reasons, including time-out and the - called <c>gen_server</c> process dying before or during the call.</p> + the atom <c>infinity</c> to wait indefinitely. + Defaults to 5000. + If no reply is received within the specified time, + this function exits the calling process with an exit term + containing <c>Reason = timeout</c> as described below. + </p> + <note> + <p> + Before OTP 24, if the caller uses (<c>try</c>...)<c>catch</c> + to avoid process exit, + and the server happens to just be late with the reply, + it may arrive to the process message queue any time later. + The calling process must therefore after catching a time-out exit + be prepared to receive garbage message(s) + on the form <c>{reference(), _}</c> + and deal with them appropriately (discard them) + so they do not clog the process message queue + or gets mistaken for other messages. + </p> + <p> + Starting with OTP 24, <c>gen_server:call</c> uses process aliases, + so late replies will not be received. + </p> + </note> + <p> + The return value <c><anno>Reply</anno></c> + is passed from the return value of <c>Module:handle_call/3</c>. + </p> + <p> + This call may exit the calling process + with an exit term on the form + <c>{Reason, Location}</c> where + <c>Location = {gen_server,call,ArgList}</c> + and <c>Reason</c> can be (at least) one of: + </p> + <taglist> + <tag><c>timeout</c></tag> + <item> + <p> + The call was aborted after waiting + <c><anno>Timeout</anno></c> milliseconds for a reply, + as described above. + </p> + </item> + <tag><c>noproc</c></tag> + <item> + <p> + The <c><anno>ServerRef</anno></c> refers to + a server by name (it is not a <c>pid()</c>) + and looking up the server process failed, + or the <c>pid()</c> was already terminated. + </p> + </item> + <tag><c>{nodedown,Node}</c></tag> + <item> + <p> + The <c><anno>ServerRef</anno></c> refers to a server + on the remote node <c>Node</c> and the connection + to that node failed. + </p> + </item> + <tag><c>calling_self</c></tag> + <item> + <p>A call to <c>self()</c> would hang indefinitely.</p> + </item> + <tag> + <c>shutdown</c><br/> + </tag> + <item> + <p> + The server was stopped during the call + by its supervisor. See also + <seemfa marker="#stop/3"><c>stop/3</c></seemfa>. + </p> + </item> + <tag> + <c>normal</c><br/> + <c>{shutdown,Term}</c><br/> + </tag> + <item> + <p> + The server stopped during the call by returning + <c>{stop,Reason,_}</c> from its + <seemfa marker="#Module:handle_call/3"> + <c>Module:handle_call/3</c> + </seemfa> + callback, without replying. See also + <seemfa marker="#stop/3"><c>stop/3</c></seemfa>. + </p> + </item> + <tag><c>_OtherTerm</c></tag> + <item> + <p> + The server process exited during the call, + with reason <c>Reason</c>. Either by returning + <c>{stop,Reason,_}</c> from its + <seemfa marker="#Module:handle_call/3"> + <c>Module:handle_call/3</c> + </seemfa> + callback (without replying), + by raising an exception, + or due to getting an exit signal it did not trap. + </p> + </item> + </taglist> </desc> </func> <func> - <name since="">cast(ServerRef, Request) -> ok</name> + <name name="cast" arity="2" since=""/> <fsummary>Send an asynchronous request to a generic server.</fsummary> - <type> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Request = term()</v> - </type> <desc> - <p>Sends an asynchronous request to the <c>ServerRef</c> of the - <c>gen_server</c> process - and returns <c>ok</c> immediately, ignoring - if the destination node or <c>gen_server</c> process does not exist. + <p> + Sends an asynchronous request to the + <c><anno>ServerRef</anno></c> of the + <c>gen_server</c> process and returns <c>ok</c> immediately, + ignoring if the destination node or <c>gen_server</c> process + does not exist. The <c>gen_server</c> process calls <seemfa marker="#Module:handle_cast/2"> - <c>Module:handle_cast/2</c></seemfa> to handle the request.</p> - <p>For a description of <c>ServerRef</c>, see - <seemfa marker="#call/2"><c>call/2,3</c></seemfa>.</p> - <p><c>Request</c> is any term that is passed as one - of the arguments to <c>Module:handle_cast/2</c>.</p> + <c>Module:handle_cast/2</c> + </seemfa> + to handle the request. + </p> + <p> + See also <c><anno>ServerRef</anno></c>'s type + <seetype marker="#server_ref"><c>server_ref()</c></seetype>. + </p> + <p> + <c><anno>Request</anno></c> is any term that is passed as + the first argument to <c>Module:handle_cast/2</c>. + </p> </desc> </func> <func> - <name since="OTP-23">check_response(Msg, RequestId) -> Result</name> - <fsummary>Check if a message is a reply from a server.</fsummary> - <type> - <v>RequestId = term()</v> - <v>Result = {reply, Reply} | no_reply | {error, {Reason, ServerRef}}</v> - <v>Msg = Reply = term()</v> - <v>Timeout = timeout()</v> - <v>Reason = term()</v> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - </type> + <name name="check_response" arity="2" since="OTP 23.0"/> + <fsummary>Check if a message is a response from a server.</fsummary> <desc> <p> - This function is used to check if a previously received - message, for example by <c>receive</c> or - <c>handle_info/2</c>, is a result of a request made with - <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>. - If <c>Msg</c> is a reply to the handle <c>RequestId</c> - the result of the request is returned in <c>Reply</c>. - Otherwise returns <c>no_reply</c> and no cleanup is done, and - thus the function must be invoked repeatedly until a reply - is returned. + Check if <c><anno>Msg</anno></c> is a response corresponding + to the request identifier <c><anno>ReqId</anno></c>. The request + must have been made by + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>, + and it must have been made by the same process calling + this function. </p> + <p> + If <c><anno>Msg</anno></c> is a response corresponding to + <c><anno>ReqId</anno></c> the response is returned; otherwise, + <c>no_reply</c> is returned and no cleanup is done, and + thus the function must be invoked repeatedly until a response + is returned. + </p> <p> - The return value <c>Reply</c> is defined in the return value - of <c>Module:handle_call/3</c>. + The return value <c><anno>Reply</anno></c> is passed from the + return value of <c>Module:handle_call/3</c>. </p> <p> The function returns an error if the <c>gen_server</c> - dies before or during this request. + died before a reply was sent. + </p> + </desc> + </func> + + <func> + <name name="check_response" arity="3" since="OTP 25.0"/> + <fsummary>Check if a message is a response from a server.</fsummary> + <desc> + <p> + Check if <c><anno>Msg</anno></c> is a response corresponding + to a request identifier saved in <c><anno>ReqIdCollection</anno></c>. + All request identifiers of <c><anno>ReqIdCollection</anno></c> + must correspond to requests that have been made using + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>, + and all request must have been made by the process calling this + function. </p> + <p> + The <c><anno>Label</anno></c> in the response equals the + <c><anno>Label</anno></c> associated with the request identifier + that the response corresponds to. The <c><anno>Label</anno></c> + of a request identifier is associated when + <seemfa marker="#reqids_add/3">saving the request id</seemfa> + in a request identifier collection, or when sending the request using + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>. + </p> + <p> + Compared to + <seemfa marker="#check_response/2"><c>check_response/2</c></seemfa>, + the returned result associated with a specific request identifier + or an exception associated with a specific request identifier will + be wrapped in a 3-tuple. The first element of this tuple equals the + value that would have been produced by <c>check_response/2</c>, + the second element equals the <c><anno>Label</anno></c> associated + with the specific request identifier, and the third element + <c><anno>NewReqIdCollection</anno></c> is a possibly modified + request identifier collection. + </p> + <p> + If <c><anno>ReqIdCollection</anno></c> is empty, the atom + <c>no_request</c> will be returned. If <c><anno>Msg</anno></c> + does not correspond to any of the request identifiers in + <c><anno>ReqIdCollection</anno></c>, the atom + <c>no_reply</c> is returned. + </p> + <p> + If <c><anno>Delete</anno></c> equals <c>true</c>, the association + with <c><anno>Label</anno></c> will have been deleted from + <c><anno>ReqIdCollection</anno></c> in the resulting + <c><anno>NewReqIdCollection</anno></c>. If + <c><anno>Delete</anno></c> equals <c>false</c>, + <c><anno>NewReqIdCollection</anno></c> will equal + <c><anno>ReqIdCollection</anno></c>. Note that deleting an + association is not for free and that a collection containing + already handled requests can still be used by subsequent calls to + <c>check_response/3</c>, + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>, + and + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>. + However, without deleting handled associations, the above calls will + not be able to detect when there are no more outstanding requests to + handle, so you will have to keep track of this some other way than + relying on a <c>no_request</c> return. Note that if you pass a + collection only containing associations of already handled or + abandoned requests to <c>check_response/3</c>, it will always + return <c>no_reply</c>. + </p> </desc> </func> <func> - <name since="">enter_loop(Module, Options, State)</name> - <name since="">enter_loop(Module, Options, State, ServerName)</name> - <name since="">enter_loop(Module, Options, State, Timeout)</name> - <name since="">enter_loop(Module, Options, State, ServerName, Timeout)</name> + <name name="enter_loop" arity="3" since=""/> + <name name="enter_loop" arity="4" clause_i="1" since=""/> + <name name="enter_loop" arity="4" clause_i="2" since=""/> + <name name="enter_loop" arity="4" clause_i="3" since=""/> + <name name="enter_loop" arity="4" clause_i="4" since=""/> + <name name="enter_loop" arity="5" clause_i="1" since=""/> + <name name="enter_loop" arity="5" clause_i="2" since=""/> + <name name="enter_loop" arity="5" clause_i="3" since=""/> <fsummary>Enter the <c>gen_server</c> receive loop.</fsummary> - <type> - <v>Module = atom()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {hibernate_after,HibernateAfterTimeout}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics</v> - <v> | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v>State = term()</v> - <v>ServerName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Timeout = int() | infinity</v> - </type> <desc> - <p>Makes an existing process into a <c>gen_server</c> process. Does not - return, instead the calling process enters the <c>gen_server</c> - process receive - loop and becomes a <c>gen_server</c> process. The process - <em>must</em> have been started using one of the start functions in - <seeerl marker="proc_lib"><c>proc_lib(3)</c></seeerl>. The user is - responsible for any initialization of the process, including - registering a name for it.</p> - <p>This function is useful when a more complex initialization procedure - is needed than the <c>gen_server</c> process behavior provides.</p> - <p><c>Module</c>, <c>Options</c>, and <c>ServerName</c> have + <p> + Makes an existing process a <c>gen_server</c> process. + Does not return, instead the calling process enters + the <c>gen_server</c> process receive loop + and becomes a <c>gen_server</c> process. + The process <em>must</em> have been started using + one of the start functions in + <seeerl marker="proc_lib"><c>proc_lib(3)</c></seeerl>. + The user is responsible for any initialization of the process, + including registering a name for it. + </p> + <p> + This function is useful when a more complex + initialization procedure is needed + than the <c>gen_server</c> process behavior provides. + </p> + <p> + <c><anno>Module</anno></c>, <c><anno>Options</anno></c>, + and <c><anno>ServerName</anno></c> have the same meanings as when calling - <seemfa marker="#start_link/3"><c>start[_link|_monitor]/3,4</c></seemfa>. - However, if <c>ServerName</c> is specified, the process must - have been registered accordingly <em>before</em> this function - is called.</p> - <p><c>State</c> and <c>Timeout</c> have the same meanings as in + <seemfa marker="#start_link/3"> + <c>start[_link|_monitor]/3,4</c> + </seemfa> + or it can be <c>self()</c> for an anonymous server, + which is the same as calling an <c>enter_loop/3,4</c> function + without a <c><anno>ServerName</anno></c> argument. + However, if <c><anno>ServerName</anno></c> is specified + (and not as <c>self()</c>), + the process must have been registered accordingly + <em>before</em> this function is called. + </p> + <p> + <c><anno>State</anno></c>, <c><anno>Timeout</anno></c>, + <c><anno>Hibernate</anno></c> and <c><anno>Cont</anno></c> have the same meanings as in the return value of - <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>. - The callback module <c>Module</c> does not need to - export an <c>init/1</c> function.</p> - <p>The function fails if the calling process was not started by a + <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>, + which is <em>not</em> called when <c>enter_loop/3,4,5</c> is used. + Note that to adhere to the + <seeguide marker="system/design_principles:gen_server_concepts"> + gen_server Behaviour + </seeguide> + such a callback function needs to be defined, + and it might as well be the one used when starting + the <c>gen_server</c> process through <c>proc_lib</c>, + and then be the one that calls <c>enter_loop/3,4,5</c>. + But if such a <c>Module:init/1</c> function + in for example error cases cannot call + <c>enter_loop/3,4,5</c>, it should return a value + that follows the type specification for + <c>Module:init/1</c> such as <c>ignore</c>, + although that value will be lost + when returning to the spawning function. + </p> + <p> + This function fails if the calling process was not started by a <c>proc_lib</c> start function, or if it is not registered - according to <c>ServerName</c>.</p> + according to <c><anno>ServerName</anno></c>. + </p> </desc> </func> <func> - <name since="">multi_call(Name, Request) -> Result</name> - <name since="">multi_call(Nodes, Name, Request) -> Result</name> - <name since="">multi_call(Nodes, Name, Request, Timeout) -> Result</name> + <name name="multi_call" arity="2" since=""/> + <name name="multi_call" arity="3" since=""/> + <name name="multi_call" arity="4" since=""/> <fsummary>Make a synchronous call to many generic servers.</fsummary> - <type> - <v>Nodes = [Node]</v> - <v> Node = atom()</v> - <v>Name = atom()</v> - <v>Request = term()</v> - <v>Timeout = int()>=0 | infinity</v> - <v>Result = {Replies,BadNodes}</v> - <v> Replies = [{Node,Reply}]</v> - <v> Reply = term()</v> - <v>BadNodes = [Node]</v> - </type> <desc> - <p>Makes a synchronous call to all <c>gen_server</c> processes locally - registered as <c>Name</c> at the specified nodes by first - sending a request to every node and then waits for - the replies. The <c>gen_server</c> process calls + <p> + Makes a synchronous call to all <c>gen_server</c> processes + locally registered as <c><anno>Name</anno></c> + at the specified nodes, + by first sending the request to the nodes, + and then waiting for the replies. + The <c>gen_server</c> processes on the nodes call <seemfa marker="#Module:handle_call/3"> - <c>Module:handle_call/3</c></seemfa> to handle the request.</p> - <p>The function returns a tuple <c>{Replies,BadNodes}</c>, where - <c>Replies</c> is a list of <c>{Node,Reply}</c> and - <c>BadNodes</c> is a list of node that either did not exist, - or where the <c>gen_server</c> <c>Name</c> did not exist or did not - reply.</p> - <p><c>Nodes</c> is a list of node names to which the request - is to be sent. Default value is the list of all known nodes - <c>[node()|nodes()]</c>.</p> - <p><c>Name</c> is the locally registered name of each - <c>gen_server</c> process.</p> - <p><c>Request</c> is any term that is passed as the first - argument to <c>Module:handle_call/3</c>.</p> - <p><c>Timeout</c> is an integer greater than zero that - specifies how many milliseconds to wait for each reply, or - the atom <c>infinity</c> to wait indefinitely. Defaults - to <c>infinity</c>. If no reply is received from a node within - the specified time, the node is added to <c>BadNodes</c>.</p> - <p>When a reply <c>Reply</c> is received from the <c>gen_server</c> - process at a node <c>Node</c>, <c>{Node,Reply}</c> is added to - <c>Replies</c>. <c>Reply</c> is defined in the return value of - <c>Module:handle_call/3</c>.</p> + <c>Module:handle_call/3</c> + </seemfa> + to handle the request. + </p> + <p> + The function returns a tuple + <c>{<anno>Replies</anno>,<anno>BadNodes</anno>}</c>, + where <c><anno>Replies</anno></c> is a list of + <c>{<anno>Node</anno>,<anno>Reply</anno>}</c> tuples, + and <c><anno>BadNodes</anno></c> is a list of nodes + that either did not exist, + where <c><anno>Name</anno></c> + was not a registered <c>gen_server</c>, + or where it did not reply. + </p> + <p> + <c><anno>Nodes</anno></c> is a list of node names + to which the request is to be sent. + Default value is the list of all known nodes + <c>[node()|nodes()]</c>. + </p> + <p> + <c><anno>Name</anno></c> is the locally registered name + for each <c>gen_server</c> process. + </p> + <p> + <c><anno>Request</anno></c> is any term that is passed + as the first argument to <c>Module:handle_call/3</c>. + </p> + <p> + <c><anno>Timeout</anno></c> is an integer that + specifies how many milliseconds to wait for all replies, + or the atom <c>infinity</c> to wait indefinitely, + which is the default. + If no reply is received from a node within the specified time, + the node is added to <c><anno>BadNodes</anno></c>. + </p> + <p> + When a reply <c><anno>Reply</anno></c> is received + from the <c>gen_server</c> process + at a node <c><anno>Node</anno></c>, + <c>{<anno>Node</anno>,<anno>Reply</anno>}</c> is added to + <c><anno>Replies</anno></c>. + <c><anno>Reply</anno></c> is passed from the return value of + <c>Module:handle_call/3</c>. + </p> <warning> - <p>If one of the nodes cannot process monitors, for example, + <p> + If one of the nodes cannot process monitors, for example, C or Java nodes, and the <c>gen_server</c> process is not started when the requests are sent, but starts within 2 seconds, this function waits the whole <c>Timeout</c>, - which may be infinity.</p> + which may be infinity. + </p> <p>This problem does not exist if all nodes are Erlang nodes.</p> </warning> - <p>To prevent late answers (after the time-out) from polluting - the message queue of the caller, a middleman process is used to - do the calls. Late answers are then discarded - when they arrive to a terminated process.</p> + <p> + To prevent late answers (after the time-out) from polluting + the message queue of the caller, a middleman process is used + to do the calls. Late answers are then discarded + when they arrive to a terminated process. + </p> </desc> </func> <func> - <name since="OTP 24.0">receive_response(RequestId, Timeout) -> Result</name> - <fsummary>Receive for a reply from a server.</fsummary> - <type> - <v>RequestId = term()</v> - <v>Result = {reply, Reply} | timeout | {error, {Reason, ServerRef}}</v> - <v>Reply = term()</v> - <v>Timeout = timeout()</v> - <v>Reason = term()</v> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - </type> + <name name="receive_response" arity="2" since="OTP 24.0"/> + <fsummary>Receive a response from a server.</fsummary> <desc> <p> - This function is used to receive a reply of a request made with - <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> - to a <c>gen_server</c> process. This function must be called - from the same process from which - <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> - was made. + Receive a response corresponding to the request identifier + <c><anno>ReqId</anno></c>. The request must have been made by + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>, + and it must have been made by the same process calling + this function. </p> <p> - <c>Timeout</c> is an integer greater then or equal to zero - that specifies how many milliseconds to wait for an reply, or - the atom <c>infinity</c> to wait indefinitely. - If no reply is received within the specified - time, the function returns <c>timeout</c>. Assuming that the + <c><anno>Timeout</anno></c> specifies how long to wait for + a response. If no response is received within the specified time, + the function returns <c>timeout</c>. Assuming that the server executes on a node supporting aliases (introduced in - OTP 24) no response will be received after a timeout. Otherwise, - a garbage response might be received at a later time. + OTP 24) the request will also be abandoned. That is, no + response will be received after a timeout. Otherwise, a + stray response might be received at a later time. </p> <p> - The return value <c>Reply</c> is defined in the return value - of <c>Module:handle_call/3</c>. + The return value <c><anno>Reply</anno></c> is passed from the + return value of <c>Module:handle_call/3</c>. </p> <p> The function returns an error if the <c>gen_server</c> - dies before or during this request. + died before a reply was sent. </p> <p> - The difference between - <seemfa marker="#wait_response/2"><c>wait_response()</c></seemfa> - and <c>receive_response()</c> is that <c>receive_response()</c> - abandons the request at timeout so that a potential future - response is ignored, while <c>wait_response()</c> does not. + The difference between <c>receive_response/2</c> and + <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa> + is that <c>receive_response/2</c> abandons the request at + timeout so that a potential future response is ignored, while + <c>wait_response/2</c> does not. </p> </desc> </func> <func> - <name since="">reply(Client, Reply) -> ok</name> + <name name="receive_response" arity="3" since="OTP 25.0"/> + <fsummary>Receive a response from a server.</fsummary> + <desc> + <p> + Receive a response corresponding to a request identifier saved + in <c><anno>ReqIdCollection</anno></c>. All request identifiers + of <c><anno>ReqIdCollection</anno></c> must correspond to requests + that have been made using + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>, + and all request must have been made by the process calling this + function. + </p> + <p> + The <c><anno>Label</anno></c> in the response equals the + <c><anno>Label</anno></c> associated with the request identifier + that the response corresponds to. The <c><anno>Label</anno></c> + of a request identifier is associated when + <seemfa marker="#reqids_add/3">adding the request id</seemfa> + in a request identifier collection, or when sending the request using + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>. + </p> + <p> + Compared to + <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa>, + the returned result associated with a specific request identifier + will be wrapped in a 3-tuple. The first element of this tuple equals + the value that would have been produced by <c>receive_response/2</c>, + the second element equals the <c><anno>Label</anno></c> associated + with the specific request identifier, and the third element + <c><anno>NewReqIdCollection</anno></c> is a possibly modified + request identifier collection. + </p> + <p> + If <c><anno>ReqIdCollection</anno></c> is empty, the atom + <c>no_request</c> will be returned. + </p> + <p> + <c><anno>Timeout</anno></c> specifies how long to wait for + a response. If no response is received within the specified time, + the function returns <c>timeout</c>. Assuming that the + server executes on a node supporting aliases (introduced in + OTP 24) all requests identified by <c><anno>ReqIdCollection</anno></c> + will also be abandoned. That is, no responses will be received + after a timeout. Otherwise, stray responses might be received + at a later time. + </p> + <p> + The difference between <c>receive_response/3</c> and + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa> + is that <c>receive_response/3</c> abandons the requests at timeout + so that potential future responses are ignored, while + <c>wait_response/3</c> does not. + </p> + <p> + If <c><anno>Delete</anno></c> equals <c>true</c>, the association + with <c><anno>Label</anno></c> will have been deleted from + <c><anno>ReqIdCollection</anno></c> in the resulting + <c><anno>NewReqIdCollection</anno></c>. If + <c><anno>Delete</anno></c> equals <c>false</c>, + <c><anno>NewReqIdCollection</anno></c> will equal + <c><anno>ReqIdCollection</anno></c>. Note that deleting an + association is not for free and that a collection containing + already handled requests can still be used by subsequent calls to + <c>receive_response/3</c>, + <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>, + and + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>. + However, without deleting handled associations, the above calls will + not be able to detect when there are no more outstanding requests to + handle, so you will have to keep track of this some other way than + relying on a <c>no_request</c> return. Note that if you pass a + collection only containing associations of already handled or + abandoned requests to <c>receive_response/3</c>, it will always block + until a timeout determined by <c><anno>Timeout</anno></c> is + triggered. + </p> + </desc> + </func> + + <func> + <name name="reply" arity="2" since=""/> <fsummary>Send a reply to a client.</fsummary> - <type> - <v>Client - see below</v> - <v>Reply = term()</v> - </type> <desc> - <p>This function can be used by a <c>gen_server</c> process to + <p> + This function can be used by a <c>gen_server</c> process to explicitly send a reply to a client that called <seemfa marker="#call/2"><c>call/2,3</c></seemfa> or <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>, - when the reply cannot be defined in the return value of + when the reply cannot be passed in the return value of <seemfa marker="#Module:handle_call/3"> - <c>Module:handle_call/3</c></seemfa>.</p> - <p><c>Client</c> must be the <c>From</c> argument provided to - the callback function. <c>Reply</c> is any term - given back to the client as the return value of - <c>call/2,3</c> or <c>multi_call/2,3,4</c>.</p> + <c>Module:handle_call/3</c></seemfa>. + </p> + <p> + <c><anno>Client</anno></c> must be the <c>From</c> argument + provided to the <c>handle_call</c> callback function. + <c><anno>Reply</anno></c> is any term + passed back to the client as the return value of + <c>call/2,3</c> or <c>multi_call/2,3,4</c>. + </p> </desc> </func> <func> - <name since="OTP 23.0">send_request(ServerRef, Request) -> RequestId</name> + <name name="reqids_add" arity="3" since="OTP 25.0"/> + <fsummary>Save a request identifier.</fsummary> + <desc> + <p> + Saves <c><anno>ReqId</anno></c> and associates a <c><anno>Label</anno></c> + with the request identifier by adding this information to + <c><anno>ReqIdCollection</anno></c> and returning the + resulting request identifier collection. + </p> + </desc> + </func> + + <func> + <name name="reqids_new" arity="0" since="OTP 25.0"/> + <fsummary>Create a new empty request identifier collection.</fsummary> + <desc> + <p> + Returns a new empty request identifier collection. A + request identifier collection can be utilized in order + the handle multiple outstanding requests. + </p> + <p> + Request identifiers of requests made by + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> + can be saved in a request identifier collection using + <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>. + Such a collection of request identifiers can later be used in + order to get one response corresponding to a request in the + collection by passing the collection as argument to + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>, + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, + or, + <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>. + </p> + <p> + <seemfa marker="#reqids_size/1"><c>reqids_size/1</c></seemfa> + can be used to determine the amount of request identifiers in a + request identifier collection. + </p> + </desc> + </func> + + <func> + <name name="reqids_size" arity="1" since="OTP 25.0"/> + <fsummary>Get size of a request identifier collection.</fsummary> + <desc> + <p> + Returns the amount of request identifiers saved in + <c><anno>ReqIdCollection</anno></c>. + </p> + </desc> + </func> + + <func> + <name name="reqids_to_list" arity="1" since="OTP 25.0"/> + <fsummary>List a request identifiers.</fsummary> + <desc> + <p> + Returns a list of <c>{<anno>ReqId</anno>, <anno>Label</anno>}</c> + tuples which corresponds to all request identifiers with their + associated labels present in the <c><anno>ReqIdCollection</anno></c> + collection. + </p> + </desc> + </func> + + <func> + <name name="send_request" arity="2" since="OTP 23.0"/> <fsummary>Sends a request to a generic server.</fsummary> - <type> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>RequestId = term()</v> - <v>Timeout = int()>0 | infinity</v> - <v>Request = term()</v> - </type> <desc> <p> - Sends a request to the <c>ServerRef</c> of the - <c>gen_server</c> process and returns a handle <c>RequestId</c>. - The return value <c>RequestId</c> shall later be used with + Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c> + to the <c>gen_server</c> process identified by <c><anno>ServerRef</anno></c> + and returns a request identifier <c><anno>ReqId</anno></c>. The return + value <c><anno>ReqId</anno></c> shall later be used with <seemfa marker="#receive_response/2"> <c>receive_response/2</c></seemfa>, <seemfa marker="#wait_response/2"> <c>wait_response/2</c></seemfa>, or <seemfa marker="#check_response/2"> <c>check_response/2</c></seemfa> - to fetch the actual result of the request. + to fetch the actual result of the request. Besides passing + the request identifier directly to these functions, it can also be + saved in a request identifier collection using + <seemfa marker="#reqids_add/3"><c>reqids_add/3</c></seemfa>. + Such a collection of request identifiers can later be used in + order to get one response corresponding to a request in the + collection by passing the collection as argument to + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>, + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, or + <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>. + If you are about to save the request identifier in a request identifier + collection, you may want to consider using + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa> + instead. </p> <p> - The call <c>gen_server:wait_response(gen_server:send_request(ServerRef,Request), Timeout)</c> - can be seen as equivalent to - <seemfa marker="#call/3"><c>gen_server:call(Server,Request,Timeout)</c></seemfa>, - ignoring the error handling. + The call <c>gen_server:receive_response(gen_server:send_request(<anno>ServerRef</anno>, + <anno>Request</anno>), Timeout)</c> can be seen as equivalent to + <seemfa marker="#call/3"><c>gen_server:call(<anno>ServerRef</anno>, <anno>Request</anno>, + Timeout)</c></seemfa>, ignoring the error handling. </p> <p> The <c>gen_server</c> process calls - <seemfa marker="#Module:handle_call/3"> <c>Module:handle_call/3</c></seemfa> + <seemfa marker="#Module:handle_call/3"> + <c>Module:handle_call/3</c> + </seemfa> to handle the request. </p> - <p><c>ServerRef</c> can be any of the following:</p> - <list type="bulleted"> - <item>The pid</item> - <item><c>Name</c>, if the <c>gen_server</c> process is locally - registered</item> - <item><c>{Name,Node}</c>, if the <c>gen_server</c> process is locally - registered at another node</item> - <item><c>{global,GlobalName}</c>, if the <c>gen_server</c> process is - globally registered</item> - <item><c>{via,Module,ViaName}</c>, if the <c>gen_server</c> process is - registered through an alternative process registry</item> - </list> - <p><c>Request</c> is any term that is passed as the first - argument to <c>Module:handle_call/3</c>.</p> + <p> + See the type + <seetype marker="#server_ref"><c>server_ref()</c></seetype> + for the possible values for <c><anno>ServerRef</anno></c>. + </p> + <p> + <c><anno>Request</anno></c> is any term that is passed + as the first argument to <c>Module:handle_call/3</c>. + </p> + </desc> + </func> + + <func> + <name name="send_request" arity="4" since="OTP 25.0"/> + <fsummary>Sends a request to a generic server.</fsummary> + <desc> + <p> + Sends an asynchronous <c>call</c> request <c><anno>Request</anno></c> + to the <c>gen_server</c> process identified by <c><anno>ServerRef</anno></c>. + The <c><anno>Label</anno></c> will be associated with the request + identifier of the operation and added to the returned request + identifier collection <c><anno>NewReqIdCollection</anno></c>. + The collection can later be used in order to get one response + corresponding to a request in the collection by passing the + collection as argument to + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>, + <seemfa marker="#wait_response/3"><c>wait_response/3</c></seemfa>, + or, + <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>. + </p> + + <p> + The same as calling + <seemfa marker="#reqids_add/3"><c>gen_server:reqids_add</c></seemfa>(<seemfa + marker="#send_request/2"><c>gen_server:send_request</c></seemfa><c>(<anno>ServerRef</anno>, + <anno>Request</anno>), <anno>Label</anno>, + <anno>ReqIdCollection</anno>)</c>, but calling <c>send_request/4</c> + is slightly more efficient. + </p> </desc> </func> <func> - <name since="">start(Module, Args, Options) -> Result</name> - <name since="">start(ServerName, Module, Args, Options) -> Result</name> + <name name="start" arity="3" since=""/> + <name name="start" arity="4" since=""/> <fsummary>Create a standalone <c>gen_server</c> process.</fsummary> - <type> - <v>ServerName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [term()]</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> <desc> - <p>Creates a standalone <c>gen_server</c> process, that is, a + <p> + Creates a standalone <c>gen_server</c> process, that is, a <c>gen_server</c> process that is not part of a supervision tree and thus has no supervisor.</p> - <p>For a description of arguments and return values, see - <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>.</p> + <p> + Other than that see + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>. + </p> </desc> </func> <func> - <name since="">start_link(Module, Args, Options) -> Result</name> - <name since="">start_link(ServerName, Module, Args, Options) -> Result</name> - <fsummary>Create a <c>gen_server</c> process in a supervision tree. + <name name="start_link" arity="3" since=""/> + <name name="start_link" arity="4" since=""/> + <fsummary> + Create a <c>gen_server</c> process in a supervision tree. </fsummary> - <type> - <v>ServerName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [term()]</v> - <v>Result = {ok,Pid} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> <desc> - <p>Creates a <c>gen_server</c> process as part of a supervision tree. + <p> + Creates a <c>gen_server</c> process as part of a supervision tree. This function is to be called, directly or indirectly, by the supervisor. For example, it ensures that - the <c>gen_server</c> process is linked to the supervisor.</p> - <p>The <c>gen_server</c> process calls - <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa> to - initialize. To ensure a synchronized startup procedure, + the <c>gen_server</c> process is linked to the supervisor. + </p> + <p> + The <c>gen_server</c> process calls + <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa> + to initialize. + To ensure a synchronized startup procedure, <c>start_link/3,4</c> does not return until - <c>Module:init/1</c> has returned.</p> - <list type="bulleted"> - <item> - <p>If <c>ServerName={local,Name}</c>, the <c>gen_server</c> process - is registered locally as <c>Name</c> using <c>register/2</c>.</p> - </item> - <item> - <p>If <c>ServerName={global,GlobalName}</c>, the <c>gen_server</c> - process id registered globally as <c>GlobalName</c> using - <seemfa marker="kernel:global#register_name/2"> - <c>global:register_name/2</c></seemfa> If no name is - provided, the <c>gen_server</c> process is not registered.</p> - </item> - <item> - <p>If <c>ServerName={via,Module,ViaName}</c>, the <c>gen_server</c> - process registers with the registry represented by <c>Module</c>. - The <c>Module</c> callback is to export the functions - <c>register_name/2</c>, <c>unregister_name/1</c>, - <c>whereis_name/1</c>, and <c>send/2</c>, which are to behave - like the corresponding functions in - <seeerl marker="kernel:global"><c>global</c></seeerl>. - Thus, <c>{via,global,GlobalName}</c> is a valid reference.</p> - </item> - </list> - <p><c>Module</c> is the name of the callback module.</p> - <p><c>Args</c> is any term that is passed as + <c>Module:init/1</c> has returned. + </p> + <p> + Using the argument <c><anno>ServerName</anno></c> + creates a <c>gen_server</c> with a registered name. + See type + <seetype marker="#server_name"><c>server_name()</c></seetype> + for different name registrations. + If no <c><anno>ServerName</anno></c> is provided, + the <c>gen_server</c> process is not registered. + </p> + <p> + <c><anno>Module</anno></c> is the name of the callback module. + </p> + <p> + <c><anno>Args</anno></c> is any term that is passed as the argument to - <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.</p> - <list type="bulleted"> - <item> - <p>If option <c>{timeout,Time}</c> is present, the <c>gen_server</c> - process is allowed to spend <c>Time</c> milliseconds - initializing or it is terminated and the start function - returns <c>{error,timeout}</c>.</p> - </item> - <item> - <p>If option <c>{hibernate_after,HibernateAfterTimeout}</c> is present, the <c>gen_server</c> - process awaits any message for <c>HibernateAfterTimeout</c> milliseconds and - if no message is received, the process goes into hibernation automatically - (by calling <seemfa marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seemfa>).</p> - </item> - <item> - <p>If option <c>{debug,Dbgs}</c> is present, - the corresponding <c>sys</c> function is called for each - item in <c>Dbgs</c>; see - <seeerl marker="sys"><c>sys(3)</c></seeerl>.</p> - </item> - <item> - <p>If option <c>{spawn_opt,SOpts}</c> is present, - <c>SOpts</c> is passed as option list to - the <c>spawn_opt</c> BIF, which is used to spawn - the <c>gen_server</c> process; see - <seemfa marker="erts:erlang#spawn_opt/2"> - <c>spawn_opt/2</c></seemfa>.</p> - </item> - </list> - <note> - <p>Using spawn option <c>monitor</c> is not - allowed, it causes the function to fail with reason - <c>badarg</c>.</p> - </note> - <p>If the <c>gen_server</c> process is successfully created and - initialized, the function returns <c>{ok,Pid}</c>, where <c>Pid</c> - is the pid of the <c>gen_server</c> process. If a process with the - specified <c>ServerName</c> exists already, the function returns - <c>{error,{already_started,Pid}}</c>, where <c>Pid</c> is - the pid of that process.</p> - <p>If <c>Module:init/1</c> fails with <c>Reason</c>, - the function returns <c>{error,Reason}</c>. If - <c>Module:init/1</c> returns <c>{stop,Reason}</c> or - <c>ignore</c>, the process is terminated and the function - returns <c>{error,Reason}</c> or <c>ignore</c>, respectively. - An exit signal with the same <c>Reason</c> (or <c>normal</c> if - <c>Module:init/1</c> returns <c>ignore</c>) is sent to linked - processes and ports.</p> + <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>. + </p> + <p> + See type + <seetype marker="#start_opt"><c>start_opt()</c></seetype> + for <c><anno>Options</anno></c> when starting + the <c>gen_server</c> process. + </p> + <p> + See type + <seetype marker="#start_ret"><c>start_ret()</c></seetype> + for a description this function's return values. + </p> </desc> </func> <func> - <name since="OTP 23.0">start_monitor(Module, Args, Options) -> Result</name> - <name since="OTP 23.0">start_monitor(ServerName, Module, Args, Options) -> Result</name> + <name name="start_monitor" arity="3" since="OTP 23.0"/> + <name name="start_monitor" arity="4" since="OTP 23.0"/> <fsummary>Create a standalone <c>gen_server</c> process.</fsummary> - <type> - <v>ServerName = {local,Name} | {global,GlobalName}</v> - <v> | {via,Module,ViaName}</v> - <v> Name = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Module = atom()</v> - <v>Args = term()</v> - <v>Options = [Option]</v> - <v> Option = {debug,Dbgs} | {timeout,Time} | {hibernate_after,HibernateAfterTimeout} | {spawn_opt,SOpts}</v> - <v> Dbgs = [Dbg]</v> - <v> Dbg = trace | log | statistics | {log_to_file,FileName} | {install,{Func,FuncState}}</v> - <v> SOpts = [term()]</v> - <v>Result = {ok,{Pid,Mon}} | ignore | {error,Error}</v> - <v> Pid = pid()</v> - <v> Error = {already_started,Pid} | term()</v> - </type> <desc> - <p>Creates a standalone <c>gen_server</c> process, that is, a + <p> + Creates a standalone <c>gen_server</c> process, that is, a <c>gen_server</c> process that is not part of a supervision tree (and thus has no supervisor) and atomically sets up a monitor to - the newly created server.</p> - <p>For a description of arguments and return values, see - <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>. - Note that the return value on successful start differs from - <c>start_link/3,4</c>. <c>start_monitor/3,4</c> will return - <c>{ok,{Pid,Mon}}</c> where <c>Pid</c> is the process identifier - of the server, and <c>Mon</c> is a reference to the monitor - set up to monitor the server. If the start is not successful, - the caller will be blocked until the <c>DOWN</c> message has - been received and removed from the message queue.</p> + the newly created server. + </p> + <p> + Other than that see + <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa>. + Note that the return value for a successful start differs + in that it returns a monitor <c>reference</c>. + See type + <seetype marker="#start_mon_ret"><c>start_mon_ret()</c></seetype>. + </p> + <p> + If the start is not successful, + the caller will be blocked until the monitor's + <c>'DOWN'</c> message has been received + and removed from the message queue. + </p> </desc> </func> <func> - <name since="OTP 18.0">stop(ServerRef) -> ok</name> - <name since="OTP 18.0">stop(ServerRef, Reason, Timeout) -> ok</name> + <name name="stop" arity="1" since="OTP 18.0"/> + <name name="stop" arity="3" since="OTP 18.0"/> <fsummary>Synchronously stop a generic server.</fsummary> - <type> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - <v>Reason = term()</v> - <v>Timeout = int()>0 | infinity</v> - </type> <desc> - <p>Orders a generic server to exit with the specified <c>Reason</c> - and waits for it to terminate. The <c>gen_server</c> process calls + <p> + Orders the generic server specified by + <c><anno>ServerRef</anno></c> to exit + with the specified <c><anno>Reason</anno></c>, + default 'normal', and waits for it to terminate. + The <c>gen_server</c> process calls <seemfa marker="#Module:terminate/2"> - <c>Module:terminate/2</c></seemfa> before exiting.</p> - <p>The function returns <c>ok</c> if the server terminates + <c>Module:terminate/2</c> + </seemfa> + before exiting. + </p> + <p> + The function returns <c>ok</c> if the server terminates with the expected reason. Any other reason than <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c> causes an error report to be issued using <seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>. - An exit signal with the same reason is sent to linked processes - and ports. - The default <c>Reason</c> is <c>normal</c>.</p> - <p><c>Timeout</c> is an integer greater than zero that + An exit signal with the same reason + is sent to linked processes and ports. + </p> + <p> + <c><anno>Timeout</anno></c> is an integer that specifies how many milliseconds to wait for the server to terminate, or the atom <c>infinity</c> to wait - indefinitely. Defaults to <c>infinity</c>. If the - server has not terminated within the specified time, a - <c>timeout</c> exception is raised.</p> - <p>If the process does not exist, a <c>noproc</c> exception - is raised.</p> + indefinitely, which is the default. If the + server has not terminated within the specified time, + the call exits the calling process + with reason <c>timeout</c>. + </p> + <p> + If the process does not exist, the call exits + the calling process with reason <c>noproc</c>, + and with reason <c>{nodedown,Node}</c> + if the connection fails to the remote <c>Node</c> + where the server runs. + </p> </desc> </func> <func> - <name since="OTP 23.0">wait_response(RequestId, Timeout) -> Result</name> - <fsummary>Wait for a reply from a server.</fsummary> - <type> - <v>RequestId = term()</v> - <v>Result = {reply, Reply} | timeout | {error, {Reason, ServerRef}}</v> - <v>Reply = term()</v> - <v>Timeout = timeout()</v> - <v>Reason = term()</v> - <v>ServerRef = Name | {Name,Node} | {global,GlobalName}</v> - <v> | {via,Module,ViaName} | pid()</v> - <v> Node = atom()</v> - <v> GlobalName = ViaName = term()</v> - </type> + <name name="wait_response" arity="2" since="OTP 23.0"/> + <fsummary>Wait or poll for a response from a server.</fsummary> <desc> <p> - This function is used to wait for a reply of a request made with - <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> - from the <c>gen_server</c> process. This function must be called - from the same process from which - <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> - was made. + Wait for a response corresponding to the request identifier + <c><anno>ReqId</anno></c>. The request must have been made by + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa>, + and it must have been made by the same process calling + this function. </p> <p> - <c>Timeout</c> is an integer greater then or equal to zero - that specifies how many milliseconds to wait for an reply, or - the atom <c>infinity</c> to wait indefinitely. - If no reply is received within the specified + <c><anno>WaitTime</anno></c> specifies how long to wait for + a reply. If no reply is received within the specified time, the function returns <c>timeout</c> and no cleanup is done, and thus the function can be invoked repeatedly until a reply is returned. </p> <p> - The return value <c>Reply</c> is defined in the return value - of <c>Module:handle_call/3</c>. + The return value <c><anno>Reply</anno></c> is passed from the + return value of <c>Module:handle_call/3</c>. </p> <p> The function returns an error if the <c>gen_server</c> - dies before or during this request. + died before a reply was sent. </p> <p> The difference between - <seemfa marker="#receive_response/2"><c>receive_response()</c></seemfa> - and <c>wait_response()</c> is that <c>receive_response()</c> - abandons the request at timeout so that a potential future - response is ignored, while <c>wait_response()</c> does not. + <seemfa marker="#receive_response/2"><c>receive_response/2</c></seemfa> + and <c>wait_response/2</c> is that <c>receive_response/2</c> + abandons the request at time-out so that a potential future + response is ignored, while <c>wait_response/2</c> does not. </p> </desc> </func> + + <func> + <name name="wait_response" arity="3" since="OTP 25.0"/> + <fsummary>Wait or poll for a response from a server.</fsummary> + <desc> + <p> + Wait for a response corresponding to a request identifier saved + in <c><anno>ReqIdCollection</anno></c>. All request identifiers + of <c><anno>ReqIdCollection</anno></c> must correspond to requests + that have been made using + <seemfa marker="#send_request/2"><c>send_request/2</c></seemfa> or + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>, + and all request must have been made by the process calling this + function. + </p> + <p> + The <c><anno>Label</anno></c> in the response equals the + <c><anno>Label</anno></c> associated with the request identifier + that the response corresponds to. The <c><anno>Label</anno></c> + of a request identifier is associated when + <seemfa marker="#reqids_add/3">saving the request id</seemfa> in + a request identifier collection, or when sending the request using + <seemfa marker="#send_request/4"><c>send_request/4</c></seemfa>. + </p> + <p> + Compared to + <seemfa marker="#wait_response/2"><c>wait_response/2</c></seemfa>, + the returned result associated with a specific request identifier + or an exception associated with a specific request identifier will + be wrapped in a 3-tuple. The first element of this tuple equals the + value that would have been produced by <c>wait_response/2</c>, + the second element equals the <c><anno>Label</anno></c> associated + with the specific request identifier, and the third element + <c><anno>NewReqIdCollection</anno></c> is a possibly modified + request identifier collection. + </p> + <p> + If <c><anno>ReqIdCollection</anno></c> is empty, <c>no_request</c> + will be returned. If no response is received before the + <c><anno>WaitTime</anno></c> timeout has triggered, the atom + <c>timeout</c> is returned. It is valid to continue waiting for a + response as many times as needed up until a response has been received + and completed by <c>check_response()</c>, <c>receive_response()</c>, + or <c>wait_response()</c>. + </p> + <p> + The difference between + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa> + and <c>wait_response/3</c> is that <c>receive_response/3</c> + abandons requests at timeout so that a potential future + responses are ignored, while <c>wait_response/3</c> does not. + </p> + <p> + If <c><anno>Delete</anno></c> equals <c>true</c>, the association + with <c><anno>Label</anno></c> will have been deleted from + <c><anno>ReqIdCollection</anno></c> in the resulting + <c><anno>NewReqIdCollection</anno></c>. If + <c><anno>Delete</anno></c> equals <c>false</c>, + <c><anno>NewReqIdCollection</anno></c> will equal + <c><anno>ReqIdCollection</anno></c>. Note that deleting an + association is not for free and that a collection containing + already handled requests can still be used by subsequent calls to + <c>wait_response/3</c>, + <seemfa marker="#check_response/3"><c>check_response/3</c></seemfa>, + and + <seemfa marker="#receive_response/3"><c>receive_response/3</c></seemfa>. + However, without deleting handled associations, the above calls will + not be able to detect when there are no more outstanding requests to + handle, so you will have to keep track of this some other way than + relying on a <c>no_request</c> return. Note that if you pass a + collection only containing associations of already handled or + abandoned requests to <c>wait_response/3</c>, it will always block + until a timeout determined by <c><anno>WaitTime</anno></c> is + triggered and then return <c>no_reply</c>. + </p> + </desc> + </func> </funcs> @@ -788,6 +1535,69 @@ gen_server:abcast -----> Module:handle_cast/2 </func> <func> + <name since="OTP 25.0">Module:format_status(Status) -> NewStatus</name> + <fsummary>Optional function for providing a term describing the + current <c>gen_server</c> status.</fsummary> + <type> + <v>Status = <seetype marker="#format_status">format_status()</seetype></v> + <v>NewStatus = <seetype marker="#format_status">format_status()</seetype></v> + </type> + <desc> + <note> + <p>This callback is optional, so callback modules need not + export it. The <c>gen_server</c> module provides a default + implementation of this function that returns the callback + module state.</p> + <p> + If this callback is exported but fails, to hide possibly sensitive + data, the default function will instead return the fact that + <c>format_status/1</c> has crashed.</p> + </note> + <p>This function is called by a <c>gen_server</c> process in the following situations:</p> + <list type="bulleted"> + <item> + <p><seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> + is invoked to get the <c>gen_server</c> status.</p> + </item> + <item> + <p>The <c>gen_server</c> process terminates abnormally and logs an error.</p> + </item> + </list> + <p> + This callback is used to limit the status of the process + returned by + <seemfa marker="sys#get_status/1"><c>sys:get_status/1,2</c></seemfa> + or sent to <seeerl marker="kernel:logger"><c>logger</c></seeerl>. + </p> + <p> + The callback gets a map <c>Status</c> + describing the current status and shall return a map + <c>NewStatus</c> with the same keys, + but it may transform some values. + </p> + <p> + Two possible use cases for this callback is to + remove sensitive information from the state + to prevent it from being printed in log files, + or to compact large irrelevant status items + that would only clutter the logs. + </p> + <p>Example:</p> + <code type="erl"><![CDATA[ +format_status(Status) -> + maps:map( + fun(state,State) -> + maps:remove(private_key, State); + (message,{password, _Pass}) -> + {password, removed}; + (_,Value) -> + Value + end, Status). +]]></code> + </desc> + </func> + + <func> <name since="OTP R13B04">Module:format_status(Opt, [PDict, State]) -> Status</name> <fsummary>Optional function for providing a term describing the current <c>gen_server</c> status.</fsummary> @@ -798,6 +1608,11 @@ gen_server:abcast -----> Module:handle_cast/2 <v>Status = term()</v> </type> <desc> + <warning> + <p>This callback is deprecated, in new code use <seemfa marker="#Module:format_status/1"> + format_status/1</seemfa>. If a <seemfa marker="#Module:format_status/1">format_status/1</seemfa> + callback exists, then this function will never be called.</p> + </warning> <note> <p>This callback is optional, so callback modules need not export it. The <c>gen_server</c> module provides a default @@ -852,18 +1667,24 @@ gen_server:abcast -----> Module:handle_cast/2 <fsummary>Handle a synchronous request.</fsummary> <type> <v>Request = term()</v> - <v>From = {pid(),Tag}</v> + <v>From = <seetype marker="#from">from()</seetype></v> <v>State = term()</v> - <v>Result = {reply,Reply,NewState} | {reply,Reply,NewState,Timeout}</v> + <v>Result = {reply,Reply,NewState}</v> + <v> | {reply,Reply,NewState,Timeout}</v> <v> | {reply,Reply,NewState,hibernate}</v> <v> | {reply,Reply,NewState,{continue,Continue}}</v> - <v> | {noreply,NewState} | {noreply,NewState,Timeout}</v> + <v> | {noreply,NewState}</v> + <v> | {noreply,NewState,Timeout}</v> <v> | {noreply,NewState,hibernate}</v> <v> | {noreply,NewState,{continue,Continue}}</v> - <v> | {stop,Reason,Reply,NewState} | {stop,Reason,NewState}</v> + <v> | {stop,Reason,Reply,NewState}</v> + <v> | {stop,Reason,NewState}</v> <v> Reply = term()</v> <v> NewState = term()</v> - <v> Timeout = int()>=0 | infinity</v> + <v> + Timeout = + <seetype marker="erts:erlang#timeout">timeout()</seetype> + </v> <v> Continue = term()</v> <v> Reason = term()</v> </type> @@ -872,45 +1693,109 @@ gen_server:abcast -----> Module:handle_cast/2 <seemfa marker="#call/2"><c>call/2,3</c></seemfa> or <seemfa marker="#multi_call/2"><c>multi_call/2,3,4</c></seemfa>, this function is called to handle the request.</p> - <p><c>Request</c> is the <c>Request</c> argument provided - to <c>call</c> or <c>multi_call</c>.</p> - <p><c>From</c> is a tuple <c>{Pid,Tag}</c>, where <c>Pid</c> is - the pid of the client and <c>Tag</c> is a unique tag.</p> <p><c>State</c> is the internal state of the <c>gen_server</c> - process.</p> - <list type="bulleted"> + process, and <c>NewState</c> a possibly updated one.</p> + <p><c>Request</c> is passed from the same argument provided + to <c>call</c> or <c>multi_call</c>.</p> + <p>The return value <c>Result</c> is interpreted as follows:</p> + <taglist> + <tag> + <c>{reply,Reply,NewState}</c><br/> + <c>{reply,Reply,NewState,_}</c> + </tag> <item> - <p>If <c>{reply,Reply,NewState}</c> is returned, - <c>{reply,Reply,NewState,Timeout}</c> or - <c>{reply,Reply,NewState,hibernate}</c>, <c>Reply</c> is - given back to <c>From</c> as the return value of - <c>call/2,3</c> or included in the return value of - <c>multi_call/2,3,4</c>. The <c>gen_server</c> process then - continues executing with the possibly updated internal state - <c>NewState</c>.</p> - <p>For a description of <c>Timeout</c> and <c>hibernate</c>, see - <seemfa marker="#Module:init/1"><c>Module:init/1</c></seemfa>.</p> + <p> + The <c>Reply</c> value is sent back to the client request + and there becomes its return value. + </p> + <p> + The <c>gen_server</c> process continues executing + with the possibly updated internal state <c>NewState</c>. + </p> </item> + <tag> + <c>{noreply,NewState}</c><br/> + <c>{noreply,NewState,_}</c> + </tag> <item> - <p>If <c>{noreply,NewState}</c> is returned, - <c>{noreply,NewState,Timeout}</c>, or - <c>{noreply,NewState,hibernate}</c>, the <c>gen_server</c> - process continues executing with <c>NewState</c>. Any reply to - <c>From</c> must be specified explicitly using - <seemfa marker="#reply/2"><c>reply/2</c></seemfa>.</p> + <p> + The <c>gen_server</c> process continues executing + with the possibly updated internal state <c>NewState</c>. + </p> + <p> + A reply to the client request has to be created by calling + <seemfa marker="#reply/2"><c>reply(From, Reply)</c></seemfa>, + either in this or in a later callback. + </p> </item> + <tag> + <c>{reply,_,_,Timeout}</c><br/> + <c>{noreply,_,Timeout}</c> + </tag> <item> - <p>If <c>{stop,Reason,Reply,NewState}</c> is returned, - <c>Reply</c> is given back to <c>From</c>.</p> + <p> + If an integer <c>Timeout</c> is provided, a time-out occurs + unless a request or a message is received within + that many milliseconds. A time-out is represented by + the atom <c>timeout</c> to be handled by the + <seemfa marker="#Module:handle_info/2"> + <c>Module:handle_info/2</c> + </seemfa> + callback function. + <c>Timeout =:= infinity</c> + can be used to wait indefinitely, which is the same as + returning a value without a <c>Timeout</c> member. + </p> </item> + <tag> + <c>{reply,_,_,hibernate}</c><br/> + <c>{noreply,_,hibernate}</c> + </tag> <item> - <p>If <c>{stop,Reason,NewState}</c> is returned, any reply - to <c>From</c> must be specified explicitly using - <seemfa marker="#reply/2"><c>reply/2</c></seemfa>. - The <c>gen_server</c> process then calls - <c>Module:terminate(Reason,NewState)</c> and terminates.</p> + <p> + The process goes into hibernation waiting for + the next message to arrive (by calling + <seemfa marker="proc_lib#hibernate/3"> + <c>proc_lib:hibernate/3</c></seemfa>). + </p> </item> - </list> + <tag> + <c>{reply,_,_,{continue,Continue}}</c><br/> + <c>{noreply,_,{continue,Continue}}</c> + </tag> + <item> + <p> + The process will execute the + <seemfa marker="#Module:handle_continue/2"> + <c>Module:handle_continue/2</c> + </seemfa> + callback function, with <c>Continue</c> as the first argument. + </p> + </item> + <tag> + <c>{stop,Reason,NewState}</c><br/> + <c>{stop,Reason,Reply,NewState}</c> + </tag> + <item> + <p> + The <c>gen_server</c> process will call + <seemfa marker="#Module:terminate/2"> + <c>Module:terminate(Reason,NewState)</c> + </seemfa> + and then terminate. + </p> + <p> + <c>{stop,_,Reply,_}</c> will create + a reply to the client request just as + <c>{reply,Reply,...}</c> while + <c>{stop,_,_}</c> will not, + so just as for <c>{noreply,NewState,...}</c> + a reply has to be created by calling + <c>reply(From, Reply)</c> + before returning <c>{stop,_,_}</c>. + </p> + </item> + </taglist> </desc> </func> @@ -920,12 +1805,16 @@ gen_server:abcast -----> Module:handle_cast/2 <type> <v>Request = term()</v> <v>State = term()</v> - <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v> + <v>Result = {noreply,NewState}</v> + <v> | {noreply,NewState,Timeout}</v> <v> | {noreply,NewState,hibernate}</v> <v> | {noreply,NewState,{continue,Continue}}</v> <v> | {stop,Reason,NewState}</v> <v> NewState = term()</v> - <v> Timeout = int()>=0 | infinity</v> + <v> + Timeout = + <seetype marker="erts:erlang#timeout">timeout()</seetype> + </v> <v> Continue = term()</v> <v> Reason = term()</v> </type> @@ -946,25 +1835,31 @@ gen_server:abcast -----> Module:handle_cast/2 <type> <v>Continue = term()</v> <v>State = term()</v> - <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v> + <v>Result = {noreply,NewState}</v> + <v> | {noreply,NewState,Timeout}</v> <v> | {noreply,NewState,hibernate}</v> <v> | {noreply,NewState,{continue,Continue}}</v> <v> | {stop,Reason,NewState}</v> <v> NewState = term()</v> - <v> Timeout = int()>=0 | infinity</v> + <v> + Timeout = + <seetype marker="erts:erlang#timeout">timeout()</seetype> + </v> <v> Continue = term()</v> <v> Reason = normal | term()</v> </type> <desc> <note> <p>This callback is optional, so callback modules need to - export it only if they return <c>{continue,Continue}</c> - from another callback. If continue is used and the callback - is not implemented, the process will exit with <c>undef</c> - error.</p> + export it only if they return one of the tuples containing + <c>{continue,Continue}</c> + from another callback. If such a <c>{continue,_}</c> tuple + is used and the callback is not implemented, + the process will exit with <c>undef</c> error.</p> </note> - <p>This function is called by a <c>gen_server</c> process whenever - a previous callback returns <c>{continue, Continue}</c>. + <p>This function is called by a <c>gen_server</c> process + whenever a previous callback returns + one of the tuples containing <c>{continue, Continue}</c>. <c>handle_continue/2</c> is invoked immediately after the previous callback, which makes it useful for performing work after initialization or for splitting the work in a callback in @@ -981,12 +1876,16 @@ gen_server:abcast -----> Module:handle_cast/2 <type> <v>Info = timeout | term()</v> <v>State = term()</v> - <v>Result = {noreply,NewState} | {noreply,NewState,Timeout}</v> + <v>Result = {noreply,NewState}</v> + <v> | {noreply,NewState,Timeout}</v> <v> | {noreply,NewState,hibernate}</v> <v> | {noreply,NewState,{continue,Continue}}</v> <v> | {stop,Reason,NewState}</v> <v> NewState = term()</v> - <v> Timeout = int()>=0 | infinity</v> + <v> + Timeout = + <seetype marker="erts:erlang#timeout">timeout()</seetype> + </v> <v> Reason = normal | term()</v> </type> <desc> @@ -1012,10 +1911,17 @@ gen_server:abcast -----> Module:handle_cast/2 <fsummary>Initialize process and internal state.</fsummary> <type> <v>Args = term()</v> - <v>Result = {ok,State} | {ok,State,Timeout} | {ok,State,hibernate}</v> - <v> | {ok,State,{continue,Continue}} | {stop,Reason} | ignore</v> + <v>Result = {ok,State}</v> + <v> | {ok,State,Timeout}</v> + <v> | {ok,State,hibernate}</v> + <v> | {ok,State,{continue,Continue}}</v> + <v> | {stop,Reason}</v> + <v> | ignore</v> <v> State = term()</v> - <v> Timeout = int()>=0 | infinity</v> + <v> + Timeout = + <seetype marker="erts:erlang#timeout">timeout()</seetype> + </v> <v> Reason = term()</v> </type> <desc> @@ -1026,35 +1932,50 @@ gen_server:abcast -----> Module:handle_cast/2 this function is called by the new process to initialize.</p> <p><c>Args</c> is the <c>Args</c> argument provided to the start function.</p> - <p>If the initialization is successful, the function is to - return <c>{ok,State}</c>, <c>{ok,State,Timeout}</c>, - <c>{ok,State,hibernate}</c>, or <c>{ok,State,{continue,Continue}}</c> - where <c>State</c> is the internal state of the <c>gen_server</c> - process.</p> - <p>If an integer time-out value is provided, a time-out occurs - unless a request or a message is received within - <c>Timeout</c> milliseconds. A time-out is represented by - the atom <c>timeout</c>, which is to be handled by the - <seemfa marker="#Module:handle_info/2"> - <c>Module:handle_info/2</c></seemfa> callback function. The atom - <c>infinity</c> can be used to wait indefinitely, this is - the default value.</p> - <p>If <c>hibernate</c> is specified instead of a time-out value, - the process goes into - hibernation when waiting for the next message to arrive (by calling - <seemfa marker="proc_lib#hibernate/3"> - <c>proc_lib:hibernate/3</c></seemfa>).</p> - <p>If <c>{continue,Continue}</c> is specified, the process will - execute the <seemfa marker="#Module:handle_continue/2"> - <c>Module:handle_continue/2</c></seemfa> callback function, with - <c>Continue</c> as the first argument.</p> - <p>If the initialization fails, the function is to return - <c>{stop,Reason}</c>, where <c>Reason</c> is any term, or - <c>ignore</c>. An exit signal with this <c>Reason</c> (or with reason - <c>normal</c> if <c>ignore</c> is returned) is sent to linked - processes and ports, notably to the process starting the gen_server - when <seemfa marker="#start_link/3"><c>start_link/3,4</c></seemfa> - is used.</p> + <p>The return value <c>Result</c> is interpreted as follows:</p> + <taglist> + <tag> + <c>{ok,State}</c><br/> + <c>{ok,State,_}</c> + </tag> + <item> + <p> + Initialization was succesful and <c>State</c> + is the internal state of the <c>gen_server</c> process. + </p> + </item> + <tag> + <c>{ok,_,Timeout}</c><br/> + <c>{ok,_,hibernate}</c><br/> + <c>{ok,_,{continue,Continue}}</c> + </tag> + <item> + <p> + See the corresponding return values from + <seemfa marker="#Module:handle_call/3"> + <c>Module:handle_call/3</c> + </seemfa> + for a description of this tuple member. + </p> + </item> + <tag> + <c>{stop,Reason}</c><br/> + <c>ignore</c> + </tag> + <item> + <p> + Initialization failed. + An exit signal with this <c>Reason</c> + (or with reason <c>normal</c> if <c>ignore</c> is returned) + is sent to linked processes and ports, + notably to the process starting the gen_server when + <seemfa marker="#start_link/3"> + <c>start_link/3,4</c> + </seemfa> + is used. + </p> + </item> + </taglist> </desc> </func> @@ -1104,11 +2025,14 @@ gen_server:abcast -----> Module:handle_cast/2 <c>'EXIT'</c> message from its parent. <c>Reason</c> is the same as in the <c>'EXIT'</c> message.</p> <p>Otherwise, the <c>gen_server</c> process terminates immediately.</p> - <p>Notice that for any other reason than <c>normal</c>, - <c>shutdown</c>, or <c>{shutdown,Term}</c>, the <c>gen_server</c> - process is assumed to terminate because of an error and - an error report is issued using - <seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>.</p> + <p> + Notice that for any other reason than <c>normal</c>, + <c>shutdown</c>, or <c>{shutdown,Term}</c>, see + <seemfa marker="#stop/3"><c>stop/3</c></seemfa>, + the <c>gen_server</c> process is assumed to terminate + because of an error, and an error report is issued using + <seeerl marker="kernel:logger"><c>logger(3)</c></seeerl>. + </p> <p>When the gen_server process exits, an exit signal with the same reason is sent to linked processes and ports.</p> </desc> |