Erlang Exercises: Ring Messages

Erlang Exercises has a great little series of programming problems that challenge you to implement solutions to some common Erlang problems. It’s a great way to learn the language. I’m going to share some of my solutions to these problems. Maybe for some discussion, maybe for some feedback from some people more experienced with Erlang, maybe just to give some new people a flavor of the language.

Interaction between processes, Concurrency

2) Write a function which starts N processes in a ring, and sends a message M times around all the processes in the ring. After the messages have been sent the processes should terminate gracefully.

-module(ring).
-export([start/2, loop/2]).
start(N, M) ->
    Seq = lists:seq(1, N),
    Messages = lists:reverse(lists:seq(0, M-1)),
    LastP = lists:foldl(fun(S, Pid) -> 
                                             spawn(?MODULE, loop, [N-S, Pid]) 
                             end, self(), Seq),
    spawn(fun() -> [ LastP ! R || R <- Messages ] end).
loop(N, NextPid) ->
    receive
        R when R > 0 -> 
            NextPid ! R,
            io:format(": Process: ~8w, Sequence#: ~w, Message#: ~w ..~n", 
                          [self(), N, R]),
            loop(N, NextPid);
        R when R =:= 0 ->
            NextPid ! R,
            io:format("* Process: ~8w, Sequence#: ~w, Message#: terminate!~n", 
                            [self(), N])
    end.

Explanation

Seq = lists:seq(1, N) and Messages = lists:reverse(lists:seq(0, M-1)),
These create lists of integers from 1 – N and then from M-1 – 0 (because of the reverse). These lists are used for creating processes and the messages that will be passed to those processes respectively.

LastP = lists:foldl(…
This is an accumulator function. The self() value passed to the function is passed in as Pid on the first iteration, but subsequent iterations get the value computed in the method with the spawn function. The final spawn Pid is returned from the accumulator and is stored in LastP. The spawn function is setting up new processes which are running the loop function with the given values.

spawn(fun() -> [ LastP ! R || R <- Messages ] end).
This is a list comprehension in Erlang. It basically takes each value from the Messages list and sends that as a message to the LastP pid which is the beginning of the Ring.

loop(N, NextPid) ->
This is the function that is being run as the processes of each of the elements of the ring.

R when R > 0 ->
When this process receives a message where the message is an integer greater than zero then write some info to the console and forward the message to the NextPid and use tail recursion to start waiting for another message.

R when R =:= 0 ->
When this process receives a message where the message is an integer that equals zero then write some info to the console and forward the message to the NextPid, but allow this process to complete naturally.

About Geoff Lane

I’m Geoff Lane and I write Zorched.net as I figure things out about software development in the hopes that it can help other people facing similar situations. Also as a thanks to the larger web community for all of the information and knowledge that they have shared. I’ve been a professional software developer since 1999 working with a variety of different technologies. I’ve worked for startups in the Silicon Valley and Chicago, IL and now work as a consultant building custom applications for clients.
This entry was posted in Erlang and tagged . Bookmark the permalink.

One Response to Erlang Exercises: Ring Messages

  1. Michael says:

    Nice write up, I also tried this problem and came up with this solution: http://sudothinker.com/2009/2/27/erlang-exercises-interaction-between-processes-concurrency-ring-code. I’m still getting my head around erlang, the foldl approach seems sweet though.

    It does look a little more cumbersome than yours but I also made each node aware of the one before it. That way each node know to only accept messages from the node before it in the ring, so that added a bit of complexity.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang="" line="" escaped=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>