Generic-user-small Peter Miller 4 posts

I’m new to Erlang and learning about it by reading through “Programming Erlang” (thank you Joe Armstrong for this excellent book). I just finished chapter 8 and was mulling over the first of the programming exercises from section 8.11:

Write a function start(AnAtom, Fun) to register AnAtomas spawn(Fun). Make sure your program works correctly in the case when two parallel processes simultaneously evaluate start/2. In this case, you must guarantee that one of these processes succeeds and the
other fails.

I was stumped at first, but then I found the following discussion post, Programming Erlang Exercise 8.11 , which presented a seemingly logical solution.

The solution in that thread did raise 2 interesting questions for me that I wanted to throw out to any experienced Erlang programmers:

1. How is the BIF register/2 function implemented to be an atomic call? I looked in the Erlang documentation online and could not find any details. As a BIF it is implemented in C, so I suppose there a lot of possibilities, but is there any way for a curious person to find out?

2. Is this problem of multiple processes trying to call register/2 at the same time something that you (experienced with Erlang) run into a lot and have to code around or is this problem more theoretical?

 
Generic-user-small Alain O'Dea 18 posts

I am new to Erlang as well and this problem had me so stumped that I nearly abandoned the book altogether. Years of using Object-oriented programming languages with bolted on concurrency support had left me with limited problem solving skills for concurrent problems.

  1. Erlang’s source is available and it should contain the implementation of register/2
  2. I imagine this is a common problem. After looking at Ladislav Lenart’s solution to 8.11 I am happy that there is a relatively concise way to solve it

Here is my version of Ladislav Lenart’s solution altered to behave like register/2 in terms of exceptions thrown and return values:

-module (start_register).
-export ([start/2]).

start(Atom, Fun) ->
    Registrant = self(),
    spawn(
        fun() ->
            try register(Atom, self()) of
                true ->
                    Registrant ! true,
                    Fun()
            catch
                error:badarg ->
                    Registrant ! false
            end
        end),
    receive
        true  -> true;
        false -> erlang:error(badarg)
    end.

This looks like the basis of a atomic transaction design pattern for Erlang. I imagine a collection of such design patterns exists. I would really like to see it if it does.

 
Generic-user-small Peter Miller 4 posts

Agreed. Thanks for sharing your version of the solution.

3 posts, 2 voices