NAME
gen_server - Generic server behavior.DESCRIPTION
This behavior module provides the server of a client-server relation. A generic server process ( gen_server) implemented using this module has a standard set of interface functions and includes functionality for tracing and error reporting. It also fits into an OTP supervision tree. For more information, see section gen_server Behaviour in OTP Design Principles. A gen_server process assumes all specific parts to be located in a callback module exporting a predefined set of functions. The relationship between the behavior functions and the callback functions is as follows:gen_server module Callback module ----------------- --------------- gen_server:start gen_server:start_monitor gen_server:start_link -----> Module:init/1 gen_server:stop -----> Module:terminate/2 gen_server:call gen_server:send_request gen_server:multi_call -----> Module:handle_call/3 gen_server:cast gen_server:abcast -----> Module:handle_cast/2 - -----> Module:handle_info/2 - -----> Module:handle_continue/2 - -----> Module:terminate/2 - -----> Module:code_change/3If a callback function fails or returns a bad value, the gen_server process terminates. A gen_server process handles system messages as described in sys(3erl). The sys module can be used for debugging a gen_server process. Notice that a gen_server process does not trap exit signals automatically, this must be explicitly initiated in the callback module. Unless otherwise stated, all functions in this module fail if the specified gen_server process does not exist or if bad arguments are specified. The gen_server process can go into hibernation (see erlang:hibernate/3) if a callback function specifies 'hibernate' instead of a time-out value. This can be useful if the server is expected to be idle for a long time. However, use this feature with care, as hibernation implies at least two garbage collections (when hibernating and shortly after waking up) and is not something you want to do between each call to a busy server. If the gen_server process needs to perform an action immediately after initialization or to break the execution of a callback into multiple steps, it can return {continue,Continue} in place of the time-out or hibernation value, which will immediately invoke the handle_continue/2 callback. If the gen_server process terminates, e.g. as a result of a function in the callback module returning {stop,Reason,NewState}, an exit signal with this Reason is sent to linked processes and ports. See Processes in the Reference Manual for details regarding error handling using exit signals.
DATA TYPES
server_name() ={local, LocalName :: atom()} |{global, GlobalName :: term()} |{via, RegMod :: module(), ViaName :: term()}
Name specification to use when starting a gen_server. See functions
start/3,4, start_link/3,4, start_monitor/3,4,
enter_loop/3,4,5, and the type server_ref() below.
- {local,LocalName}:
- Register the gen_server locally as LocalName using register/2.
- {global,GlobalName}:
- Register the gen_server process id globally as GlobalName using global:register_name/2.
- {via,RegMod,ViaName}:
- Register the gen_server process with the registry represented by RegMod. The RegMod callback is to export the functions register_name/2, unregister_name/1, whereis_name/1, and send/2, which are to behave like the corresponding functions in global. Thus, {via,global,GlobalName} is a valid reference equivalent to {global,GlobalName}.
server_ref() =pid() |(LocalName :: atom()) |{Name :: atom(), Node :: atom()} |{global, GlobalName :: term()} |{via, RegMod :: module(), ViaName :: term()}
Server specification to use when addressing a gen_server. See
call/2,3, cast/2, send_request/2,
check_response/2, wait_response/2, stop/2,3 and the type
server_name() above.
It can be:
- pid():
- The gen_server's process identifier.
- LocalName:
- The gen_server is locally registered as LocalName with register/2.
- {Name,Node}:
- The gen_server is locally registered on another node.
- {global,GlobalName}:
- The gen_server is globally registered in global.
- {via,RegMod,ViaName}:
- The gen_server is registered in an alternative process registry. The registry callback module RegMod is to export functions register_name/2, unregister_name/1, whereis_name/1, and send/2, which are to behave like the corresponding functions in global. Thus, {via,global,GlobalName} is the same as {global,GlobalName}.
start_opt() ={timeout, Timeout :: timeout()} |{spawn_opt, SpawnOptions :: [proc_lib:spawn_option()]} |enter_loop_opt()
Options that can be used when starting a gen_server server through, for
example, start_link/3,4.
- {timeout,Timeout}:
- How many milliseconds the gen_server process is allowed to spend initializing or it is terminated and the start function returns {error,timeout}.
- {spawn_opt,SpawnOptions}:
- The SpawnOptions option list is passed to the function used to spawn the gen_server; see spawn_opt/2.
Note:
Using spawn option monitor is not allowed, it causes a badarg
failure.
- enter_loop_opt():
- See the type enter_loop_opt() below for more start options that are also allowed by enter_loop/3,4,5.
enter_loop_opt() ={hibernate_after, HibernateAfterTimeout :: timeout()} |{debug, Dbgs :: [sys:debug_option()]}
Options that can be used when starting a gen_server server through
enter_loop/3-5 or the start functions such as start_link/3,4.
- {hibernate_after,HibernateAfterTimeout}:
- Specifies that the gen_server process awaits any message for HibernateAfterTimeout milliseconds and if no message is received, the process goes into hibernation automatically (by calling proc_lib:hibernate/3).
- {debug,Dbgs}:
- For every entry in Dbgs, the corresponding function in sys(3erl) is called.
start_ret() ={ok, Pid :: pid()} | ignore | {error, Reason :: term()}
Return value from the start/3,4 and start_link/3,4 functions.
- {ok,Pid}:
- The gen_server process was succesfully created and initialized, with the process identifier Pid.
- {error,{already_started,OtherPid}}:
- A process with the specified ServerName exists already with the process identifier OtherPid. This gen_server was not started.
- ignore:
- Module:init/1 returned ignore, the gen_server process is terminated. An exit signal normal is sent to linked processes and ports.
- {error,Reason}:
- Module:init/1 returned {stop,Reason} or failed with Reason. The gen_server process is terminated and an exit signal with the same Reason is sent to linked processes and ports.
start_mon_ret() ={ok, {Pid :: pid(), MonRef :: reference()}} |ignore |{error, Reason :: term()}
Return value from the start_monitor/3,4 functions. The same as type
start_ret() except that for a succesful start it returns both the
process identifier Pid and a monitor/2,3 reference()
MonRef.
from() = {Client :: pid(), Tag :: reply_tag()}
Destination, given to the gen_server as the first argument to the
callback function Module:handle_call/3, to be used by the when replying
through reply/2 (instead of through the callback function's return
value) to the process Client that has called the gen_server
using call/2,3. Tag is a term that is unique for this
call/request instance.
reply_tag()
A handle that associates a reply to the corresponding request.
request_id()
An opaque request identifier. See send_request/2 for details.
request_id_collection()
An opaque collection of request identifiers ( request_id()) where each
request identifier can be associated with a label chosen by the user. For more
information see reqids_new/0.
response_timeout() = timeout() | {abs, integer()}
Used to set a time limit on how long to wait for a response using either
receive_response/2, receive_response/3, wait_response/2,
or wait_response/3. The time unit used is millisecond. Currently
valid values:
- 0..4294967295:
- Timeout relative to current time in milliseconds.
- infinity:
- Infinite timeout. That is, the operation will never time out.
- {abs, Timeout}:
- An absolute Erlang monotonic time timeout in milliseconds. That is, the operation will time out when erlang:monotonic_time(millisecond) returns a value larger than or equal to Timeout. Timeout is not allowed to identify a time further into the future than 4294967295 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 ( request_id_collection()) , since you do not have to recalculate the relative time until the deadline over and over again.
format_status() =#{state => term(),message => term(),reason => term(),log => [sys:system_event()]}
A map that describes the gen_server status. The keys are:
New associations may be added to the status map without prior notice.
- state:
- The internal state of the gen_server process.
- message:
- The message that caused the server to terminate.
- reason:
- The reason that caused the server to terminate.
- log:
-
The sys log of the server.
EXPORTS
abcast(Name :: atom(), Request :: term()) -> abcast
abcast(Nodes :: [node()], Name :: atom(), Request :: term()) -> abcast
Sends an asynchronous request to the gen_server processes locally
registered as Name at the specified nodes. The function returns
immediately and ignores nodes that do not exist, or where the
gen_server Name does not exist. The gen_server processes
call Module:handle_cast/2 to handle the request.
For a description of the arguments, see multi_call/2,3,4.
call(ServerRef :: server_ref(), Request :: term()) -> Reply :: term()
call(ServerRef :: server_ref(), Request :: term(), Timeout :: timeout()) -> Reply :: term()
Makes a synchronous call to the ServerRef of the gen_server
process by sending a request and waiting until a reply arrives or a time-out
occurs. The gen_server process calls Module:handle_call/3 to
handle the request.
See also ServerRef's type server_ref().
Request is any term that is passed as the first argument to
Module:handle_call/3.
Timeout is an integer that specifies how many milliseconds to wait for a
reply, or the atom infinity 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 Reason = timeout as
described below.
The return value Reply is passed from the return value of
Module:handle_call/3.
This call may exit the calling process with an exit term on the form {Reason,
Location} where Location = {gen_server,call,ArgList} and
Reason can be (at least) one of:
Note:
Before OTP 24, if the caller uses ( try...)catch 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 {reference(), _} and deal with them appropriately (discard
them) so they do not clog the process message queue or gets mistaken for other
messages.
Starting with OTP 24, gen_server:call uses process aliases, so late
replies will not be received.
- timeout:
- The call was aborted after waiting Timeout milliseconds for a reply, as described above.
- noproc:
- The ServerRef refers to a server by name (it is not a pid()) and looking up the server process failed, or the pid() was already terminated.
- {nodedown,Node}:
- The ServerRef refers to a server on the remote node Node and the connection to that node failed.
- calling_self:
- A call to self() would hang indefinitely.
- shutdown
-
- normal
-
- _OtherTerm:
- The server process exited during the call, with reason Reason. Either by returning {stop,Reason,_} from its Module:handle_call/3 callback (without replying), by raising an exception, or due to getting an exit signal it did not trap.
cast(ServerRef :: server_ref(), Request :: term()) -> ok
Sends an asynchronous request to the ServerRef of the gen_server
process and returns ok immediately, ignoring if the destination node or
gen_server process does not exist. The gen_server process calls
Module:handle_cast/2 to handle the request.
See also ServerRef's type server_ref().
Request is any term that is passed as the first argument to
Module:handle_cast/2.
check_response(Msg, ReqId) -> Result
Types:
Msg = term()
ReqId = request_id()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result = Response | no_reply
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Check if Msg is a response corresponding to the request identifier
ReqId. The request must have been made by send_request/2, and it
must have been made by the same process calling this function.
If Msg is a response corresponding to ReqId the response is
returned; otherwise, no_reply is returned and no cleanup is done, and
thus the function must be invoked repeatedly until a response is returned.
The return value Reply is passed from the return value of
Module:handle_call/3.
The function returns an error if the gen_server died before a reply was
sent.
check_response(Msg, ReqIdCollection, Delete) -> Result
Types:
Msg = term()
ReqIdCollection = request_id_collection()
Delete = boolean()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result =
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | no_reply
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | no_reply
Check if Msg is a response corresponding to a request identifier saved in
ReqIdCollection. All request identifiers of ReqIdCollection must
correspond to requests that have been made using send_request/2 or
send_request/4, and all request must have been made by the process
calling this function.
The Label in the response equals the Label associated with the
request identifier that the response corresponds to. The Label of a
request identifier is associated when saving the request id in a request
identifier collection, or when sending the request using
send_request/4.
Compared to check_response/2, 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 check_response/2, the
second element equals the Label associated with the specific request
identifier, and the third element NewReqIdCollection is a possibly
modified request identifier collection.
If ReqIdCollection is empty, the atom no_request will be returned.
If Msg does not correspond to any of the request identifiers in
ReqIdCollection, the atom no_reply is returned.
If Delete equals true, the association with Label will have
been deleted from ReqIdCollection in the resulting
NewReqIdCollection. If Delete equals false,
NewReqIdCollection will equal ReqIdCollection. 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
check_response/3, receive_response/3, and
wait_response/3. 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 no_request return. Note that if you pass a collection only
containing associations of already handled or abandoned requests to
check_response/3, it will always return no_reply.
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term()) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), ServerName :: server_name() | pid()) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), Timeout :: timeout()) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), Hibernate :: hibernate) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), Cont :: {continue, term()}) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), ServerName :: server_name() | pid(), Timeout :: timeout()) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), ServerName :: server_name() | pid(), Hibernate :: hibernate) -> no_return()
enter_loop(Module :: module(), Options :: [enter_loop_opt()], State :: term(), ServerName :: server_name() | pid(), Cont :: {continue, term()}) -> no_return()
Makes an existing process a gen_server process. Does not return, instead
the calling process enters the gen_server process receive loop and
becomes a gen_server process. The process must have been started
using one of the start functions in proc_lib(3erl). The user is
responsible for any initialization of the process, including registering a
name for it.
This function is useful when a more complex initialization procedure is needed
than the gen_server process behavior provides.
Module, Options, and ServerName have the same meanings as
when calling start[_link|_monitor]/3,4 or it can be self() for
an anonymous server, which is the same as calling an enter_loop/3,4
function without a ServerName argument. However, if ServerName
is specified (and not as self()), the process must have been registered
accordingly before this function is called.
State, Timeout, Hibernate and Cont have the same
meanings as in the return value of Module:init/1, which is not
called when enter_loop/3,4,5 is used. Note that to adhere to the
gen_server Behaviour such a callback function needs to be defined, and it
might as well be the one used when starting the gen_server process
through proc_lib, and then be the one that calls
enter_loop/3,4,5. But if such a Module:init/1 function in for
example error cases cannot call enter_loop/3,4,5, it should return a
value that follows the type specification for Module:init/1 such as
ignore, although that value will be lost when returning to the spawning
function.
This function fails if the calling process was not started by a proc_lib
start function, or if it is not registered according to
ServerName.
multi_call(Name :: atom(), Request :: term()) -> {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}
multi_call(Nodes :: [node()], Name :: atom(), Request :: term()) -> {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}
multi_call(Nodes :: [node()], Name :: atom(), Request :: term(), Timeout :: timeout()) -> {Replies :: [{Node :: node(), Reply :: term()}], BadNodes :: [node()]}
Makes a synchronous call to all gen_server processes locally registered
as Name at the specified nodes, by first sending the request to the
nodes, and then waiting for the replies. The gen_server processes on
the nodes call Module:handle_call/3 to handle the request.
The function returns a tuple {Replies,BadNodes}, where Replies is
a list of {Node,Reply} tuples, and BadNodes is a list of nodes
that either did not exist, where Name was not a registered
gen_server, or where it did not reply.
Nodes is a list of node names to which the request is to be sent. Default
value is the list of all known nodes [node()|nodes()].
Name is the locally registered name for each gen_server process.
Request is any term that is passed as the first argument to
Module:handle_call/3.
Timeout is an integer that specifies how many milliseconds to wait for
all replies, or the atom infinity to wait indefinitely, which is the
default. If no reply is received from a node within the specified time, the
node is added to BadNodes.
When a reply Reply is received from the gen_server process at a
node Node, {Node,Reply} is added to Replies. Reply
is passed from the return value of Module:handle_call/3.
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.
Warning:
If one of the nodes cannot process monitors, for example, C or Java nodes, and
the gen_server process is not started when the requests are sent, but
starts within 2 seconds, this function waits the whole Timeout, which
may be infinity.
This problem does not exist if all nodes are Erlang nodes.
receive_response(ReqId, Timeout) -> Result
Types:
ReqId = request_id()
Timeout = response_timeout()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result = Response | timeout
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Receive a response corresponding to the request identifier ReqId. The
request must have been made by send_request/2, and it must have been
made by the same process calling this function.
Timeout specifies how long to wait for a response. If no response is
received within the specified time, the function returns timeout.
Assuming that the server executes on a node supporting aliases (introduced in
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.
The return value Reply is passed from the return value of
Module:handle_call/3.
The function returns an error if the gen_server died before a reply was
sent.
The difference between receive_response/2 and wait_response/2 is
that receive_response/2 abandons the request at timeout so that a
potential future response is ignored, while wait_response/2 does
not.
receive_response(ReqIdCollection, Timeout, Delete) -> Result
Types:
ReqIdCollection = request_id_collection()
Timeout = response_timeout()
Delete = boolean()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result =
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | timeout
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | timeout
Receive a response corresponding to a request identifier saved in
ReqIdCollection. All request identifiers of ReqIdCollection must
correspond to requests that have been made using send_request/2 or
send_request/4, and all request must have been made by the process
calling this function.
The Label in the response equals the Label associated with the
request identifier that the response corresponds to. The Label of a
request identifier is associated when adding the request id in a request
identifier collection, or when sending the request using
send_request/4.
Compared to receive_response/2, 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
receive_response/2, the second element equals the Label
associated with the specific request identifier, and the third element
NewReqIdCollection is a possibly modified request identifier
collection.
If ReqIdCollection is empty, the atom no_request will be returned.
Timeout specifies how long to wait for a response. If no response is
received within the specified time, the function returns timeout.
Assuming that the server executes on a node supporting aliases (introduced in
OTP 24) all requests identified by ReqIdCollection will also be
abandoned. That is, no responses will be received after a timeout. Otherwise,
stray responses might be received at a later time.
The difference between receive_response/3 and wait_response/3 is
that receive_response/3 abandons the requests at timeout so that
potential future responses are ignored, while wait_response/3 does not.
If Delete equals true, the association with Label will have
been deleted from ReqIdCollection in the resulting
NewReqIdCollection. If Delete equals false,
NewReqIdCollection will equal ReqIdCollection. 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
receive_response/3, check_response/3, and
wait_response/3. 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 no_request return. Note that if you pass a collection only
containing associations of already handled or abandoned requests to
receive_response/3, it will always block until a timeout determined by
Timeout is triggered.
reply(Client :: from(), Reply :: term()) -> ok
This function can be used by a gen_server process to explicitly send a
reply to a client that called call/2,3 or multi_call/2,3,4, when
the reply cannot be passed in the return value of Module:handle_call/3.
Client must be the From argument provided to the
handle_call callback function. Reply is any term passed back to
the client as the return value of call/2,3 or
multi_call/2,3,4.
reqids_add(ReqId :: request_id(), Label :: term(), ReqIdCollection :: request_id_collection()) -> NewReqIdCollection :: request_id_collection()
Saves ReqId and associates a Label with the request identifier by
adding this information to ReqIdCollection and returning the resulting
request identifier collection.
reqids_new() -> NewReqIdCollection :: request_id_collection()
Returns a new empty request identifier collection. A request identifier
collection can be utilized in order the handle multiple outstanding requests.
Request identifiers of requests made by send_request/2 can be saved in a
request identifier collection using reqids_add/3. 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 receive_response/3, wait_response/3, or,
check_response/3.
reqids_size/1 can be used to determine the amount of request identifiers
in a request identifier collection.
reqids_size(ReqIdCollection :: request_id_collection()) -> integer() >= 0
Returns the amount of request identifiers saved in ReqIdCollection.
reqids_to_list(ReqIdCollection :: request_id_collection()) -> [{ReqId :: request_id(), Label :: term()}]
Returns a list of {ReqId, Label} tuples which corresponds to all request
identifiers with their associated labels present in the ReqIdCollection
collection.
send_request(ServerRef :: server_ref(), Request :: term()) -> ReqId :: request_id()
Sends an asynchronous call request Request to the
gen_server process identified by ServerRef and returns a request
identifier ReqId. The return value ReqId shall later be used
with receive_response/2, wait_response/2, or
check_response/2 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 reqids_add/3. 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 receive_response/3, wait_response/3,
or check_response/3. If you are about to save the request identifier in
a request identifier collection, you may want to consider using
send_request/4 instead.
The call gen_server:receive_response(gen_server:send_request(ServerRef,
Request), Timeout) can be seen as equivalent to
gen_server:call(ServerRef, Request, Timeout), ignoring the error
handling.
The gen_server process calls Module:handle_call/3 to handle the
request.
See the type server_ref() for the possible values for ServerRef.
Request is any term that is passed as the first argument to
Module:handle_call/3.
send_request(ServerRef :: server_ref(), Request :: term(), Label :: term(), ReqIdCollection :: request_id_collection()) -> NewReqIdCollection :: request_id_collection()
Sends an asynchronous call request Request to the
gen_server process identified by ServerRef. The Label
will be associated with the request identifier of the operation and added to
the returned request identifier collection NewReqIdCollection. 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
receive_response/3, wait_response/3, or,
check_response/3.
The same as calling
gen_server:reqids_add(gen_server:send_request(ServerRef,
Request), Label, ReqIdCollection), but calling send_request/4 is
slightly more efficient.
start(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret()
start(ServerName :: server_name(), Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret()
Creates a standalone gen_server process, that is, a gen_server
process that is not part of a supervision tree and thus has no supervisor.
Other than that see start_link/3,4.
start_link(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret()
start_link(ServerName :: server_name(), Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_ret()
Creates a gen_server 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 gen_server process is linked to the supervisor.
The gen_server process calls Module:init/1 to initialize. To
ensure a synchronized startup procedure, start_link/3,4 does not return
until Module:init/1 has returned.
Using the argument ServerName creates a gen_server with a
registered name. See type server_name() for different name
registrations. If no ServerName is provided, the gen_server
process is not registered.
Module is the name of the callback module.
Args is any term that is passed as the argument to Module:init/1.
See type start_opt() for Options when starting the
gen_server process.
See type start_ret() for a description this function's return
values.
start_monitor(Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_mon_ret()
start_monitor(ServerName :: server_name(), Module :: module(), Args :: term(), Options :: [start_opt()]) -> start_mon_ret()
Creates a standalone gen_server process, that is, a gen_server
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.
Other than that see start_link/3,4. Note that the return value for a
successful start differs in that it returns a monitor reference. See
type start_mon_ret().
If the start is not successful, the caller will be blocked until the monitor's
'DOWN' message has been received and removed from the message
queue.
stop(ServerRef :: server_ref()) -> ok
stop(ServerRef :: server_ref(), Reason :: term(), Timeout :: timeout()) -> ok
Orders the generic server specified by ServerRef to exit with the
specified Reason, default 'normal', and waits for it to terminate. The
gen_server process calls Module:terminate/2 before exiting.
The function returns ok if the server terminates with the expected
reason. Any other reason than normal, shutdown, or
{shutdown,Term} causes an error report to be issued using
logger(3erl). An exit signal with the same reason is sent to linked
processes and ports.
Timeout is an integer that specifies how many milliseconds to wait for
the server to terminate, or the atom infinity to wait indefinitely,
which is the default. If the server has not terminated within the specified
time, the call exits the calling process with reason timeout.
If the process does not exist, the call exits the calling process with reason
noproc, and with reason {nodedown,Node} if the connection fails
to the remote Node where the server runs.
wait_response(ReqId, WaitTime) -> Result
Types:
ReqId = request_id()
WaitTime = response_timeout()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result = Response | timeout
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Wait for a response corresponding to the request identifier ReqId. The
request must have been made by send_request/2, and it must have been
made by the same process calling this function.
WaitTime specifies how long to wait for a reply. If no reply is received
within the specified time, the function returns timeout and no cleanup
is done, and thus the function can be invoked repeatedly until a reply is
returned.
The return value Reply is passed from the return value of
Module:handle_call/3.
The function returns an error if the gen_server died before a reply was
sent.
The difference between receive_response/2 and wait_response/2 is
that receive_response/2 abandons the request at time-out so that a
potential future response is ignored, while wait_response/2 does
not.
wait_response(ReqIdCollection, WaitTime, Delete) -> Result
Types:
ReqIdCollection = request_id_collection()
WaitTime = response_timeout()
Delete = boolean()
Response =
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
Result =
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | timeout
{reply, Reply :: term()} |
{error, {Reason :: term(), server_ref()}}
{Response,
Label :: term(),
NewReqIdCollection :: request_id_collection()} |
no_request | timeout
Wait for a response corresponding to a request identifier saved in
ReqIdCollection. All request identifiers of ReqIdCollection must
correspond to requests that have been made using send_request/2 or
send_request/4, and all request must have been made by the process
calling this function.
The Label in the response equals the Label associated with the
request identifier that the response corresponds to. The Label of a
request identifier is associated when saving the request id in a request
identifier collection, or when sending the request using
send_request/4.
Compared to wait_response/2, 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 wait_response/2, the
second element equals the Label associated with the specific request
identifier, and the third element NewReqIdCollection is a possibly
modified request identifier collection.
If ReqIdCollection is empty, no_request will be returned. If no
response is received before the WaitTime timeout has triggered, the
atom timeout 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 check_response(), receive_response(), or
wait_response().
The difference between receive_response/3 and wait_response/3 is
that receive_response/3 abandons requests at timeout so that a
potential future responses are ignored, while wait_response/3 does not.
If Delete equals true, the association with Label will have
been deleted from ReqIdCollection in the resulting
NewReqIdCollection. If Delete equals false,
NewReqIdCollection will equal ReqIdCollection. 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
wait_response/3, check_response/3, and
receive_response/3. 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 no_request return. Note that if you pass a collection only
containing associations of already handled or abandoned requests to
wait_response/3, it will always block until a timeout determined by
WaitTime is triggered and then return no_reply.
CALLBACK FUNCTIONS
The following functions are to be exported from a gen_server callback module.EXPORTS
Module:code_change(OldVsn, State, Extra) -> {ok, NewState} | {error, Reason}
Types:
OldVsn = Vsn | {down, Vsn}
Vsn = term()
State = NewState = term()
Extra = term()
Reason = term()
Vsn = term()
Note:
This callback is optional, so callback modules need not export it. If a release
upgrade/downgrade with Change={advanced,Extra} specified in the
appup file is made when code_change/3 isn't implemented the
process will crash with an undef exit reason.
Types:
Status = format_status()
NewStatus = format_status()
Note:
This callback is optional, so callback modules need not export it. The
gen_server module provides a default implementation of this function
that returns the callback module state.
If this callback is exported but fails, to hide possibly sensitive data, the
default function will instead return the fact that format_status/1 has
crashed.
- *
- sys:get_status/1,2 is invoked to get the gen_server status.
- *
- The gen_server process terminates abnormally and logs an error.
format_status(Status) -> maps:map( fun(state,State) -> maps:remove(private_key, State); (message,{password, _Pass}) -> {password, removed}; (_,Value) -> Value end, Status).
Types:
Opt = normal | terminate
PDict = [{Key, Value}]
State = term()
Status = term()
Warning:
This callback is deprecated, in new code use format_status/1. If a
format_status/1 callback exists, then this function will never be called.
Note:
This callback is optional, so callback modules need not export it. The
gen_server module provides a default implementation of this function
that returns the callback module state.
- *
- One of sys:get_status/1,2 is invoked to get the gen_server status. Opt is set to the atom normal.
- *
- The gen_server process terminates abnormally and logs an error. Opt is set to the atom terminate.
Types:
Request = term()
From = from()
State = term()
Result = {reply,Reply,NewState}
| {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {reply,Reply,NewState,{continue,Continue}}
| {noreply,NewState}
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,Reply,NewState}
| {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = timeout()
Continue = term()
Reason = term()
| {reply,Reply,NewState,Timeout}
| {reply,Reply,NewState,hibernate}
| {reply,Reply,NewState,{continue,Continue}}
| {noreply,NewState}
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,Reply,NewState}
| {stop,Reason,NewState}
Reply = term()
NewState = term()
Timeout = timeout()
Continue = term()
Reason = term()
Whenever a gen_server process receives a request sent using
call/2,3 or multi_call/2,3,4, this function is called to handle
the request.
State is the internal state of the gen_server process, and
NewState a possibly updated one.
Request is passed from the same argument provided to call or
multi_call.
The return value Result is interpreted as follows:
- {reply,Reply,NewState}
-
The gen_server process continues executing with the possibly updated
internal state NewState.
- {noreply,NewState}
-
A reply to the client request has to be created by calling reply(From,
Reply), either in this or in a later callback.
- {reply,_,_,Timeout}
-
- {reply,_,_,hibernate}
-
- {reply,_,_,{continue,Continue}}
-
- {stop,Reason,NewState}
-
{stop,_,Reply,_} will create a reply to the client request just as
{reply,Reply,...} while {stop,_,_} will not, so just as for
{noreply,NewState,...} a reply has to be created by calling
reply(From, Reply) before returning {stop,_,_}.
Types:
Request = term()
State = term()
Result = {noreply,NewState}
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Continue = term()
Reason = term()
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Continue = term()
Reason = term()
Whenever a gen_server process receives a request sent using cast/2
or abcast/2,3, this function is called to handle the request.
For a description of the arguments and possible return values, see
Module:handle_call/3.
Types:
Continue = term()
State = term()
Result = {noreply,NewState}
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Continue = term()
Reason = normal | term()
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Continue = term()
Reason = normal | term()
Note:
This callback is optional, so callback modules need to export it only if they
return one of the tuples containing {continue,Continue} from another
callback. If such a {continue,_} tuple is used and the callback is not
implemented, the process will exit with undef error.
Types:
Info = timeout | term()
State = term()
Result = {noreply,NewState}
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Reason = normal | term()
| {noreply,NewState,Timeout}
| {noreply,NewState,hibernate}
| {noreply,NewState,{continue,Continue}}
| {stop,Reason,NewState}
NewState = term()
Timeout = timeout()
Reason = normal | term()
Note:
This callback is optional, so callback modules need not export it. The
gen_server module provides a default implementation of this function
that logs about the unexpected Info message, drops it and returns
{noreply, State}.
Types:
Args = term()
Result = {ok,State}
| {ok,State,Timeout}
| {ok,State,hibernate}
| {ok,State,{continue,Continue}}
| {stop,Reason}
| ignore
State = term()
Timeout = timeout()
Reason = term()
| {ok,State,Timeout}
| {ok,State,hibernate}
| {ok,State,{continue,Continue}}
| {stop,Reason}
| ignore
State = term()
Timeout = timeout()
Reason = term()
Whenever a gen_server process is started using start/3,4,
start_monitor/3,4, or start_link/3,4, this function is called by
the new process to initialize.
Args is the Args argument provided to the start function.
The return value Result is interpreted as follows:
- {ok,State}
-
- {ok,_,Timeout}
-
- {stop,Reason}
-
Types:
Reason = normal | shutdown | {shutdown,term()}
| term()
State = term()
Note:
This callback is optional, so callback modules need not export it. The
gen_server module provides a default implementation without cleanup.
- *
- The gen_server process has been set to trap exit signals.
- *
- The shutdown strategy as defined in the child specification of the supervisor is an integer time-out value, not brutal_kill.
SEE ALSO
gen_event(3erl), gen_statem(3erl), proc_lib(3erl), supervisor(3erl), sys(3erl)stdlib 4.2 | Ericsson AB |