and a new state are given in the return value. The process’s “eternally looping function” is implemented in the library. This allows for simple unit testing of the callback functions.
Large Erlang applications make heavy use of behaviours—direct use of the raw message-sending or receiving expressions is uncommon. In the Ericsson AXD301 telecom switch—the largest known Erlang project, with more than a million lines of code—nearly all the application code uses standard behaviours, a majority of which are the server behaviour. 4
Erlang’s OTP standard library provides three main behaviours:
Generic server (gen_server). The generic server is the most common behaviour. It abstracts the standard request-response message pattern used in client-server or remote procedure call protocols in distributed computing. It provides sophisticated functionality beyond our simple server module: • Responses can be delayed by the server or delegated to another process. • Calls have optional timeouts. • The client monitors the server so that it receives immediate notification of a server failure instead of waiting for a timeout.
Generic finite state machine (gen_fsm). Many concurrent algorithms are specified in terms of a finite state machine model. The OTP library provides a convenient behaviour for this pattern. The message protocol that it obeys provides for clients to signal events to the state machine, possibly waiting for a synchronous reply. The application-specific callbacks handle
these events, receiving the current state and passing a new state as a return value.
Generic event handler (gen_event). An event manager is a process that receives events as incoming messages, then dispatches those events to an arbitrary number of event handlers, each of which has its own module of callback functions and its own private state. Handlers can be dynamically added, changed, and deleted. Event handlers run application code for events, frequently selecting a subset to take action upon and ignoring the rest. This behaviour naturally models logging, monitoring, and “pubsub” systems. The OTP library provides off-the-shelf
Make a set of server calls in parallel and return a % list of their corresponding results.
Calls is a list of {Server, Params} tuples. multicall1(Calls) ->
Ids = [send_call(Call) || Call <- Calls], collect_replies(Ids).
4
Send a server call request message. send_call({Server, Params}) ->
Id = make_ref(),
Server {call, {self(), Id}, Params}, Id.
Collect all replies in order. collect_replies(Ids) ->
[receive {Id, Result} -> Result end || Id <- Ids].
multicall2(Calls) ->
Parent = self(),
Pids = [worker(Parent, Call) || Call <- Calls], wait_all(Pids).
worker(Parent, {Server, Params}) ->
spawn(fun() -> create a worker process
Result = server:call(Server, Params),
Parent {self(), Result}
end).
wait_all(Pids) ->
References:
Archives