[erlang-questions] How to do counters?

Witold Baryluk baryluk@REDACTED
Tue Jun 30 00:36:00 CEST 2009


Dnia 2009-06-29, pon o godzinie 16:02 -0400, Jarrod Roberson pisze:
> On Mon, Jun 29, 2009 at 1:18 PM, Jarrod Roberson <jarrod@REDACTED>wrote:
> 
> > 2009/6/29 Witold Baryluk <baryluk@REDACTED>
> >
> 
> so this is what have so far, is this the best "erlangy" way of doing this?
> 
> -module(counter).
> 
> -export([inc/1,inc/2,dec/1,dec/2,current/1,reset/1,start/1,loop/1]).
> 
> start(Name) ->
>    register(list_to_atom(Name),spawn(counter,loop,[0])),
>    ok.
> 
> inc(Name, Amount) ->
>     list_to_atom(Name) ! {inc_counter, Amount},
>     current(Name).
> 
> inc(Name) ->
>    inc(Name, 1).
> 
> dec(Name, Amount) ->
>     list_to_atom(Name) ! {dec_counter, Amount},
>     current(list_to_atom(Name)).
> 
> dec(Name) ->
>    dec(Name, 1).
> 
> current(Name) ->
>    list_to_atom(Name) ! {get_counter, self()},
>    receive
>        { counter_value, Count } ->
>            Count
>    end.
> 
> reset(Name) ->
>     list_to_atom(Name) ! reset,
>     current(Name).
> 
> loop(Counter) ->
>    receive
>        {inc_counter, Amount} ->
>            NewCounter = Counter + Amount;
>        {dec_counter, Amount} ->
>            NewCounter = Counter - Amount;
>        {get_counter, Pid} ->
>            Pid ! { counter_value, Counter },
>            NewCounter = Counter;
>        reset ->
>            NewCounter = 0
>    end,
>    loop(NewCounter).
I would suggest move all list_to_atom to separate function (even if
it only have one call), so it will be easier to change scheme of nameing
your counters. Prefixing it is also quite good so it will be unique. You
can only register processes using atoms, so yes it is pretty only
possible solution. It is also good, that registering of process will
fail if there is another instance running with the same name. You can
implement own name->pid, scheme, but it isn't simplest one. Most
important is to have clear interface.

There is also problem with your receive statements. What if request or
replay will be lost? You will block forever. You can add timeout, and
throw exception. But if you will call it again, there is possibility
that on receive you will receive actually previous message. This can be
also true if another counter process will send you reply. In received
message you have no idea which one of the counter replayed you. You
should add it's name or pid to pattern match, eventually use unique
references (make_ref/0). If you will do this you still need to remember
that eventually this replay can be in your mailbox, so there should be
some way to remove them later and ignore.



Generally most "erlangy" way is to use gen_server for such purposes,
because they are well designed and handles well lots of corner cases. :)


-- 
Witold Baryluk
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: To jest cz??? wiadomo?ci podpisana cyfrowo
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20090629/71335ee8/attachment.bin>


More information about the erlang-questions mailing list