FREE BURMA!

( ? , qUeStIoNMaRk )

Seeking for a sustainable amount of chaos. AKA an electronic stream of consciousness about software engineering, open source, life. By Marco Fabbri.

August 22, 2007

Erlang in the evening

Let’s unveil the (not so) misterious bug from yesterday Erlang post…
The auto-increment counter controller receives two kind of messages:

a start message which starts the timered auto-increment;
a stop message which stops the auto-increment.

An implicit assumption on the sequence of messages has been made; no two following messages are equal, i.e. assuming the auto_counter process starting as inactive every message history is produced by the following grammar:

S, scope
S -> start A
A -> stop, S | stop

What happens if the auto_counter process starts as inactive and the message history is of the kind start, stop, stop, start?
When the first start message is received the process starts incrementing (the message match the pattern in the receive expression in the inactive auto_counter function clause (auto_counter(inactive, CounterP, DeltaT)). The process stops incrementing when the first stop message (the message matches the stop pattern in the receive expression and the inactive auto_counter function is called) . Hence, when the second stop message arrives, the function clause being evaluated is auto_counter(inactive, CounterP, DeltaT) which holds indefinitely until a start message is received; bottom-line the second stop message is left in the process’ message box. When the second start message it matches the start pattern and the active auto_counter function gets called (remember: the second stop message is waiting in the message box for a “disaster” to happen :-) ). At this point as the active auto_counter function is being evaluated (which comprises a receive start expression) the process receives the second stop message which causes the auto-increment to stop. Is this behaviour supposed to be correct?
The last post didn’t go into a deep analysis of the problem and its requirements, but now has the problem is in the spotlight time has come to take a decision, the actual implemented behaviour is… WRONG! (an assumption holding true for fairly high percent of the programs being developed). I (the self-appointed project leader) expect the auto-increment process to filter out every stop message received when stopped and every start message when started. This requirements sounds a lot like having a filter on the messages sent to the auto_counter process, so let’s define a process with this capability:

Two “states”, active/inactive which translates in two functions clauses: increment_filter(active,...), increment_filter(inactive,...);
increment_filter(inactive,...) discards stop messages (which means after receiving one calls increment_filter(inactive,...)) and when a start message is received a start message is sent to the auto_counter process and increment_filter(active,...) gets called;
increment_filter(active,...) discards start messages (which means after receiving one calls increment_filter(active,...)) and when a stop message is received a stop message is sent to the auto_counter process and increment_filter(inactive,...) gets called;
knowledge of the auto_counter process identefier.

Here it follows the straightforward implementation:

autoinc_filter(active, Auto_counterP) ->
    receive start ->
            autoinc_filter(active, Auto_counterP);
            stop ->
            Auto_counterP ! stop,
            autoinc_filter(inactive, Auto_counterP)
    end;
autoinc_filter(inactive, Auto_counterP) ->
    receive stop ->
            autoinc_filter(inactive, Auto_counterP);
            start ->
            Auto_counterP ! start,
            autoinc_filter(active, Auto_counterP)
    end.

The impact of the change on the previously developed system (even in the case that it was running) is minimal: only a new process is required to be spwaned; this definetely makes the case for true incremental development and it resembles a kind of living system (interesting reading: The Pinocchio Problem), capable of gracefully growing and evolving.

Another approach to the fixing of the spotted bug would have been discarding the “un-interesting” messages right into the auto_counter function:

auto_counter(active, CounterP, DeltaT) ->
        Activity = receive
                stop -> inactive;
                start -> active
        after DeltaT ->
                CounterP ! inc,
                active
        end,
        auto_counter(Activity, CounterP, DeltaT);
auto_counter(inactive, CounterP, DeltaT) ->
        receive
            start -> auto_counter(active, CounterP, DeltaT);
            stop  -> auto_counter(inactive, CounterP, DeltaT)
        end

This solution seems at first sight correct: althougth the change at the inactiveclause is rather simple, the change at the active clause is trickier enough you end up with a failing system. Every time a start message arrives the timeout gets reset, so the increment doesn’t happen every Delta and the timing is rather faulty; if the arrival rate of the “un-interesting” messages is high enough, let’s say greater than 1/(DeltaT-1) , the counter gets never incremented no matter how long the process keeps on evaluating the auto_counter(active,...) function. This ending osservation is purposed to point out that if you try to twist an inherently counterrent problem in a sequential way the odds you end up screwed are quite high. Erlang encourages to keep concurrent things concurrent, and this is, in my humble opinion, an important point (in software systems engineering) that Erlang gets it right. The world is parallel, better to keep it in mind ;-) .

Comments »

The URI to TrackBack this entry is: http://questionmark.blogsome.com/2007/08/22/erlang-in-the-evening/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>


Get free blog up and running in minutes with Blogsome | Theme designs available here