Gen_server and Gen_fsm questions

Casper casper2000a@REDACTED
Tue Jan 4 08:54:38 CET 2005


Hi Vance,

Thanks a lot for your advice.

Gen_server:
Ahh... that's a clever method you explained.

Gen_fsm:
If I have one/two process for each call, then if I maintain let's say
100,000 simultaneous calls, I will have to create 200,000 gen_fsm, ie.
Processes. Is that a Good method? Will that create unnecessary system
overhead?

Cheers,
Eranga




-----Original Message-----
From: Vance Shipley [mailto:vances@REDACTED] 
Sent: Tuesday, January 04, 2005 1:27 PM
To: Casper
Cc: erlang-questions@REDACTED
Subject: Re: Gen_server and Gen_fsm questions

On Tue, Jan 04, 2005 at 10:58:45AM +0600, Casper wrote:
}  
}  Gen_server:
}  1) Does gen_server execute code synchronously?

It processes a request until the handler returns.  In a simple
case the handler returns {reply, Reply, State} and then the client's
call to gen_server:call/2 returns Reply.  It can have multiple requests
outstanding however by returning {noreply, State} in which case the
vlient's call to gen_server:call/2 doesn't return.  At some point later
the gen_server process calls gen_server:reply/2 to cause the clients
call to return a reply.

}  2) Even though gen_server Cast is a asynchronous request, in terms of
}  Gen_server, it's synchronous code execution, right?

The gen_server process still exicutes it's handler in the same way
however the client's call to gen_server:cast/2 returns immediately.

}  3) So if I need to process things in parallel in the server side, how can
I
}  do it?

By having the gen_server process spawn a new process to carry out the 
task in it's handler and return {noreply, State}.  Later when the worker
process finishes it sends the result to the gen_server process which
uses gen_server:reply/2 to send the reply to the client.

-behaviour(gen_server).

init(_) ->
   {ok, gb_trees:empty()}.

handle_call({request, time}, From, State) ->
   Server = self(),
   F = fun() -> gen_server:cast(Server, {result, self(), time()}) end,
   {noreply, gb_trees:insert(proc_lib:spawn(F), From, State)}.

handle_cast({result, Pid, Result}, State) ->
   From = gb_trees:get(Pid, State),
   gen_server:reply(From, Result),
   {noreply, gb_trees:delete(Pid, State)}.

1> {ok, S} = gen_server:start_link(async_server, [], []).
{ok,<0.36.0>}
2> gen_server:call(S, {request, time}).
{7,21,32}


}  4) Then what happens to the Gen_server State, if parallel execution can
}  happen?
  
Well there is no parallel execution so there is only one state.  You
will want to use the State to keep track of the outstanding replies
you still need to send and anything else you need to complete them.
In the example above I use a gb_tree to keep an entry for each pid()
started and store the From value needed to send the reply.

}  Gen_Fsm:
}  1) As I can see Gen_fsm starts its own process for each state machine.

It's no different a gen_server in this regard.

}  2) Because of that if I use Gen_fsm to maintain Call (Telecom switch or
PBX
}  kind of system) handling, for each Call a new process starts.

You start a gen_fsm the same way you start a gen_server.

}  3) Is this a good method?

Yes, one process for each concurrent activity.  It is common to use
two processes for a call, one for each side; incoming and outgoing.

}  4) Or rather should I use an Erlang Dict to have Call Circuit State
machines
}  and update each machine in every call event?
  
No.  Use processes as the main building block.


	-Vance




More information about the erlang-questions mailing list