[erlang-questions] A couple of design questions

mats cronqvist masse@REDACTED
Fri Mar 27 09:07:48 CET 2009


Steve Davis <steven.charles.davis@REDACTED> writes:

> Hi all,
>
> I am working on a gs-style interface to wx, and was hoping someone may
> have an opinion on a couple of design issues:
>
> 1) I've been maintaining an ets table to cope with naming/references
> and command events. In order to keep the references unique across
> multiple UI instances (processes), I've used a key format that is
> basically {self(), name}/{reference, data}. I've had problems
> convincing myself that these tables are safe as they must be marked
> "public". However, I'm now thinking that these references would be
> better off in the process dictionary (something I am usually cautious
> of doing) as these stored references are, or should be (a) private to
> the process, (b) "transient" with the process, and (c) irrelevant
> outside the process. So my question here is: in this case, is it as
> valid as it seems to me now to the use of the process dictionary to
> store a fair amount of data, and if so what limitations should I watch
> out for?

  Oldtimers avoid the process dict because it used to be slow. "Real"
  functional programmers avoid both ets and the dict for religious
  reasons.  AFAIK, there's no real reason to avoid the process dict in
  favor of ets.

> 2) Starting the UI instance process merely uses spawn (and returns the
> pid to the calling process). It's troubled me that perhaps the GUI
> process should be more "OTP". However, given that this is a framework
> that builds on wxe (with the graphics server already there), my
> thinking is that the ownership (and supervision) of the UI process
> would be better implemented by the calling application, since it can
> link and supervise the UI. Making the UI run off a gen_server seems an
> unnecessary complexity in the design of the framework. My question
> here is: Simple though this is, is my thinking correct?

  In my experience, it pays off to use gen_server right from the
  start. Otherwise, once the state machine starts to grow, you'll
  either refactor to a gen_server or wish you had.
 
  gen_server has no noticeable performance penalty, but you do need to
  write a bunch of boilerplate. You might want to check out this(*)
  code for an example of how to abstract away the boilerplate.

  mats

(*) gen_serv implements a gen_server callback. It will delegate to its
own callback if possible (it's some sort of inheritance). E.g. given
this module;

-module('foo').
-author('Mats Cronqvist').
-export([handle_call/3]).

handle_call(Msg,From,State) -> 
  io:fwrite("~p~n",[{Msg,From,State}]),
  {ok,State}.

  you can do this;
 1> gen_serv:start(foo).
 2> gen_server:call(foo,bla).
{bla,{<0.28519.2>,#Ref<0.0.12.74776>},undefined}

 http://code.google.com/p/eper/source/browse/trunk/src/gen_serv.erl




More information about the erlang-questions mailing list