[erlang-questions] Programming Erlang Exercise 8.11

Charles Gordon charles.gordon@REDACTED
Thu Sep 20 21:30:18 CEST 2007


> From: Ladislav Lenart <lenartlad@REDACTED>
>
> start(Atom, Fun) when is_atom(Atom), is_function(Fun, 0) ->
>         Sender = self(),
>         Fun2 = fun() ->
>                 case catch register(Atom, self()) of
>                         true ->
>                                 Sender ! {started, self()},
>                                 Fun();
>                         _ ->
>                                 Sender ! {already_running, self()}
>                 end
>         end,
>         Pid = spawn(Fun2),
>         receive
>                 {started, Pid} ->
>                         {ok, Pid};
>                 {already_running, Pid} ->
>                         already_running
>         end.


Thanks Ladislav, this seems to be the correct solution to the problem.
Thanks also to Chris Newcombe who patiently explained to me how this works.
For the future readers of this list, I'll reproduce my understanding of it
here.

The key insight I was missing is that "register/2" does an atomic
test-and-set, so it will only register a given atom once, regardless of how
it is called (and how many processes try concurrently). My original solution
had the obvious race condition between the "whereis/1" and "register/2"
calls. Just getting rid of the call to "whereis/1" wouldn't fix the problem,
since you would have already spawned the process by the time you realized
someone else had beaten you to registering it. Ladislav's solution starts a
process every time "start/2" is called and then has that function register
itself. If it succeeds, it runs the original fun, so now the registered atom
is linked to the original fun (as the problem requires).

I assumed this meant that the "register/2" BIF was keeping some global
shared state that was also accessible via "whereis/1". Chris explained that
a better way to look at it, in Erlang, is that register/2 acts as a server
for some state (in this case, the registered atoms) and is able to
atomically update that state when called by clients. So you can think of it
as having a serialized queue of requests and responding to them in order.
I'm not sure if that is how it is actually implemented, but it makes sense
(to me) to think of it that way.

Any mistakes in the above explanation are definitely mine!

Thanks again,
Charles Gordon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20070920/d5039bac/attachment.htm>


More information about the erlang-questions mailing list