[erlang-questions] Semaphores

ok ok@REDACTED
Thu Mar 15 07:10:52 CET 2007


On 15 Mar 2007, at 3:17 pm, Danesh Daroui wrote:
> I have seen (even posts in this mailing list) that there is a need  
> to have Semaphores
> in Erlang

This is debatable.
Semaphores are a rather dangerous and low level construction,
and Erlang is not really supposed to be a dangerous and low level  
language.

> and since Erlang offers concurrency, Semaphores can be useful in  
> data sharing.

But for most purposes, Erlang *doesn't* share data.

> I would be glad to have your feedbacks.

feedback is a mass noun.
Source files should be kept to a maximum width of 80 columns;
the RETURN key is there for a reason and should be used often.
Source code should be indented using your text editor's indentation
features, NOT one tab per tab stop.  8-column indentations (what you
get when you use the tab key) are eye-jarring.

Just like the RETURN key, the space bar is there on your keyboard for
a reason.  It should be used between "words"; see the Ada Quality &  
Style
Guidelines for some nearly excellent advice about this.  Infix operators
like -> are usually best treated as words, punctuation marks are usually
best treated like punctuation marks in English.

Unlike Smalltalk, which originated the practice because the Smalltalk  
character
set didn't *have* any suitable character like "_", Erlang *does* have  
"_" and
*does* allow it in multi_word_identifiers.  (As, for that matter,  
does modern
Smalltalk.)  BaStudlyCapsIsNotVeryEasyToRead.

Your new function would be better as

     new(Initial_Count) when is_integer(Initial_Count), Initial_Count  
 >= 0 ->
	spawn(fun () -> semaphore_loop(Initial_Count) end).

There are a number of really basic problems with semaphores.

For one thing, unless you speak Dutch, 'p' and 'v' have no intrinsic  
meaning
to you.  (If I say that I think 'p' means 'passieren', that just  
shows you that
my ignorance of Dutch is unbounded.)  Even 'increment' and  
'decrement' would be
better names (whichever way around they go), or 'acquire'/'release'.

One big problem is that it is too easy to forget to increment the  
counter again.
Smalltalk handles this with 'aSemaphore critical: aBlock'; the Erlang  
equivalent
would be
	critical(Semaphore, Fun) ->
	    p(Semaphore),
	    Answer = Fun().
	    v(Semaphore),
	    Answer.

BUT with extra stuff in there to catch exceptions, release the  
semaphore, and
re-raise the exceptions.  Eeek.

Oh heck, I leave you to the abundant literature on semaphores to find  
out why
semaphores have a bad name.

There really isn't much point in writing

	case (SemValue>0) of
	    true -> ~a~
	    false -> ~b~
	end

First, the parentheses are worse than useless here.
Second, you really need spaces around the > because it is hard to see  
without them.
Third, what's wrong with

	if Count > 0 ->
	    ~a~
	 ; Count <= 0 ->
	    ~b~
	end

making it completely obvious when each case applies?

Above all, all you really want to do is this:

	semaphore_loop(Count) ->
	    receive
	        {acquire,Pid} when Count > 0 ->
		    Pid!granted,
		    semaphore_loop(Count - 1)
	      ; release ->
	            semaphore_loop(Count + 1)
	      ; stop ->
	            ok
	    end.


	new(Initial_Count) when is_integer(Count), Count >= 0 ->
	    spawn(fun () -> semaphore_loop(Initial_Count) end).

         acquire(Semaphore) ->
	    Semaphore!{acquire,self()}.

	release(Semaphore) ->
	    Semaphore!release.

	stop(Semaphore) ->
	    Semaphore!stop.

The next problem is to ensure that a semaphore can only be released  
by a process
which had previously acquired it.

Oh yes, lists:append([PID], WaitList)
can be written more clearly as
	[PID] ++ WaitList
and more clearly still as
	[PID | WaitList].





More information about the erlang-questions mailing list