Make lock(&foo) syntax nominally lock the subroutine
authorFather Chrysostomos <sprout@cpan.org>
Mon, 15 Aug 2011 02:16:14 +0000 (19:16 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 15 Aug 2011 13:20:19 +0000 (06:20 -0700)
commitf79aa60b66082c8bff80f325979742bfb6c73709
tree9abac236ef8e21df8d6080190f3e12e2aae9eadd
parent186abd568524c217f6dbd29891eef21c3cd2a3b0
Make lock(&foo) syntax nominally lock the subroutine

In 5.10, lock(&foo) was an error for non-lvalue subs.  For lvalue
subs, it passed &foo to the lockhook and return \&foo.

In 5.12, lock(&foo) was still an error for non-lvalue subs.  For
lvalue subs, it would pass &foo to the lockhook and then either
trip an assertion (-DDEBUGGING) or return &foo, resulting in inter-
esting bugs.

Commit f4df43b5e changed lock(&lvalue_sub) to call the sub and lock
its return value.

As Reini Urban pointed out in
<CAHiT=DE5cVZbuCR3kb=Q5oCa18vo3jr5jZKmURHYha2PwF4pEQ@mail.gmail.com>,
locking a subroutine does have its uses.

Since lock(&foo) has never really worked anyway, we can still
change this.

So, for lvalue subs, this reverts back to the 5.10 behaviour.  For
non-lvalue subs, it now behaves the same way, the lvalue flag making
no difference.  Note that it still causes an error at run-time, if
threads::shared is loaded, as its lockhook is conservative in what
it accepts.

But this change allows for future extensibility, unlike f4df43b5e.

A note about the implementation: There are two pieces of code (at
least) in op.c that convert an entersub op into an rv2cv, one in
S_doref and the other in Perl_op_lvalue_flags.  Originally (before
f4df43b5e) it was S_doref that took care of that for OP_LOCK.  But
Perl_op_lvalue_flags is called first, so it would assume it was an
assignment to a sub call and croak if there was no lvalue sub in the
symbol table.  This commit adds back the special case for OP_LOCK, but
in Perl_op_lvalue_flags, not S_doref.
op.c
pod/perldelta.pod
pod/perlfunc.pod
pp.c
t/op/cproto.t
t/op/lock.t