Nick Ing-Simmons wrote:

> The tricky bit i.e. the _design_ - is to separate the op-ness from the
> var-ness. I assume that there is something akin to hv_fetch_ent() which
> takes a flag to say - by the way this is going to be stored ...

I'm not entirely clear on what you mean here - is it something like
this, where $a is shared and $b is unshared?

        $a = $a + $b;

because there is a potential race condition between the initial fetch of
say $a and the assignment to it?  That is, beteen us fetching $a and
putting the new value back into it, someone else may have snuck in and
changed its value.

My response to this is simple - tough.  If you choose to do this then it
your own fault for not locking properly around the update.  Here's the
rationale:

Firstly, I'm assuming that perl will protect $a internally to make sure
that it doesn't become inconsistent, so that the interpreters don't
scramble each others innards.  For example, you would probably want
shared variables to me protected by reader/writer locks so that multiple
threads/interpreters can read concurrently from a shared SV safely, but
only a single writer is allowed.  Just fetching the value would take out
a shared lock, whereas changing that variable would require an exclusive
lock.  A writer would have to wait until all readers had released their
lockse etc.  This is all standard thread programming stuff.

The problem with saying that perl should ensure that the operation "$a =
$a + $b" is atomic is that it is an unbounded problem.  When should $a
be automatically locked and unlocked?  At the beginning and end of the
+= op?  at the beginning and end of the line?  the block?  the sub?  You
get my point - in general it is impossible to know the intent of the
programmer with respect to how long he requires exclusive use of $a. 
That's why threaded programs use explicit locks - they are how the
programmer tells the machine that he wants everyone elses hands off of a
piece of shared state.  I'm sure that you can see the potential
difference in the outcome of the following two bits of code:

        lock($@);
        while (defined(my $line = <$foo>)) {
                push(@a, $line);
        }
        unlock(@a);

and

        while(defined(my $line = <$foo>)) {
                lock(@a);
                push(@a, $line);
                unlock(@a);
        }

If @a is being concurrently updated by two threads using the same code
fragment, in the first case all the lines form a given file will be in a
block, in the second they will be potentially intermingled.  I know of
no way save putting explicit locks that the perl interpreter could know
which of the two choices were correct.  Locking primitives are not put
into threads libraries just to make the programmers life burdensome,
they are there so that the programmer can make sure his program behaves
as intended.  Trying to remove the need for explicit locking is a fools
errand.  It is about as sensible as removing BLOCKS and getting perl to
guess where they should go.

-- 
Alan Burlison

Reply via email to