[erlang-questions] Counters

Richard A. O'Keefe ok@REDACTED
Tue Apr 26 05:53:38 CEST 2016



On 25/04/16 10:36 AM, Donald Steven wrote:
> With the archived help provided by Alpar Juttner and Witold Baryluk, I 
> thought I would share (primarily for other newbees like me), one way 
> to implement counters.
>
> Best,
>
> Don
>
> =================================================================================== 
>
>
> %%%-------------------------------------------------------------------------- 
>
> %%% File       : counter.erl, version 1.00
> %%% Author     : Donald Steven <impartialmusic@REDACTED>, adapted from 
> code
> %%%              suggested by Alpar Juttner and Witold Baryluk of the 
> Erlang
> %%%              community
> %%% Purpose    : To demonstrate multiple independent counters
> %%% Created    : 24 Apr 2016
> %%% Invocation : erlc counter.erl
> %%%              erl -noshell -s counter main -s init stop
> %%%-------------------------------------------------------------------------- 
>
>
> -module(counter).
> -export([main/0,inc/1,dec/1,current/1,start/1,loop/1]).
>
> %%%-------------------------------------------------------------------------- 
>
> %%% Fun     : inc(X), dec(X), current(X)
> %%% Purpose : Increment, decrement the counter X, and provide its current
> %%%           state
> %%% Created : 24 Apr 2016
> %%%-------------------------------------------------------------------------- 
>
>
> inc(X) ->
>     list_to_atom("counter_" ++ [X]) ! inc_counter,
>     ok.

NO!  DANGER, WILL ROBINSON!

Atoms are held in a fixed size table and are not garbage collected.
Constructing new atoms at run time is generally a bad idea.

That was the first thing I thought of when I saw this, but it's
actually not the worst problem.  The only values of X that make
list_to_atom("counter_" ++ [X]) legal are the integers 0 to 255
inclusive.  That is, a counter name X *must* be an integer 0 to 255
AND YOU HAVE NOT DOCUMENTED THIS.

Your module should NOT be registering counters.

There should simply be functions

     new_counter() ->
         new_counter(0).

     new_counter(N) ->
         spawn(fun () -> loop(N) end).

and the *CALLER* can register a counter if there is a reason to.

It's not just that doing it that way removes an arbitrary limitation,
it's that as things stand, a malicious program can easily destroy all
the counters.  *And* it avoids the problem where two processes
both try to start counter 5.  I have used two programming languages
(Fortran and IMP) in which I/O channels were referred to by number
and it was seriously painful trying to combine libraries that assumed
they had sole control of channel N.

By the way, I didn't see anything to *terminate* a counter.



More information about the erlang-questions mailing list