two style questions

Ulf Wiger ulf@REDACTED
Sun Jul 17 17:36:13 CEST 2005


Den 2005-07-17 03:19:43 skrev Charles Blair <chas@REDACTED>:

>
> as a relative newcomer to erlang, i read the thread Meyer, OO and
> concurrency with some interest, and wanted to isolate two comments for
> further discussion here, as i have some questions about them: i want
> to be sure i'm on the right track for the work i'm doing.
>
> uffe writes:
>
>      One could imagine a specification stating that a process waiting
>      indefinitely should be automatically removed, but I have never
>      considered it a problem that Erlang doesn't do so.
>
>      In Erlang, a process waiting indefinitely for something that will
>      never occur is probably (but not certainly) in a faulty state.
>
> here's my first question: the only way i know of to keep an ets table
> open in memory is to spawn a process that opens it, does whatever else
> it has to, then recurs on itself waiting for a message that never
> comes: is there another way to keep an ets table open indefinitely? on
> a related note, does it make sense to call erlang:hibernate right
> before the recursive step?

No, there's basically no other way. A process has to own the ets
table, and when the process dies, the ets table is automatically
removed. What one often does, if it's desireable that the ets
table outlive the process using it (e.g. if the table has a very
large amount of data that you don't want to lose even if the
process restarts), is to let another process create the ets
table. One convenient way to achieve this is to use mnesia
(you can, for example create a ram_copy, local_content table
in mnesia, and then use mnesia:activity(ets, fun() ... end)
to access it.)

A quick and dirty approach for a supervised process is to
create the ets table in the start function, before spawning
the process. This makes the supervisor the owner of the ets
table (which then has to be a public named_table). This is
quite convenient, but can cause some problems during soft
upgrade, since there is no straightforward way to e.g.
rename or delete the ets table without restarting the
supervisor.)

erlang:hibernate/3 is essentially an optimization with
a curious semantic twist(*), but the main point of calling
hibernate/3 is to save some memory. Otherwise, it doesn't
really make sense.

(*) The twist is that the {M,F,A} passed to hibernate will
be called when a message has arrived. This is the only
reasonable way to have code run _before_ consuming a message.
One possible use of this could be to detect that new code
has been loaded, and perhaps transform state before jumping
back into action code.


> vance writes:
>
>      ... I would add a warning about registered processes. I rarely
>      use them anymore as I am a purist and in the pursuit of
>      functional programming I avoid needing them. There are many
>      reasons to do so, much more than using the process dictionary,
>      but again doing so is often due to laziness.
>
> here's my second question. i've implemented the server part of a
> client/server protocol where data are delivered in chunks of a certain
> size. in addition to the data, the server sends the client a
> resumption token which, when sent back to the server by the client,
> lets the server send along the next chunk of data. there are several
> ways of implementing this, but the way i've chosen to do it is to use
> a registered process to keep state, passing along the name of the
> process in the resumption token. when i get the token back from the
> client, i look up the relevant process, and pick up where i left
> off. the question is, is this a reasonable implementation from the
> erlang perspective? (i might add that the clients can be written in
> any language; token passing is done via http. i might also add that i
> switched to erlang from common lisp to force myself to write in a
> purely functional style.)


If the state can outlive the process holding it (which is possible
for example if the state is stored in ets (and another process
owns the ets table, as explained above), then it can make sense
to use the registered name of a process. Otherwise, using the
pid seems quite sensible, except for the issue of having to
serialize the pid and present it in the external protocol.
Using a symbolic name migh look a bit better there.

You might even want to use another kind of registry than the
built-in one, since you'd otherwise have to call list_to_atom/1
based on information in the http message. This is a potential
memory leak, as atoms are never garbage collected. There is a
registry in jungerl, called proc_reg. I've done some work on
it that hasn't yet made it into jungerl. The version at Jungerl
actually failed a QuickCheck session, so I've re-written it
completely. There is a race condition in the code that could
theoretically bite someone who uses the library in a very
unintuitive way. I heartily recommend the new version, which
has yet to be released.  ;-)

/Uffe




More information about the erlang-questions mailing list