On Wednesday 15 March 2006 18:55, Perrin Harkins wrote: > On Wed, 2006-03-15 at 12:23 -0500, Geoffrey Young wrote: > > I actually thing that would be somewhat common. and as I understand > > things, the fix would require the middle step to be > > > > -- next handler > > my $o = $r->pnotes('foo'); > > $o->set(bar => 1); # sets $o->{_bar} = 1 > > $r->pnotes(foo => $o); > > > > in order for $o to maintain it's internal state. is that right? if so, > > I don't like that very much. > > I agree, cloning is not the answer. What you want really want here is > for it to behave like a normal perl variable assignment, i.e. if you > assign a reference, it stays a reference, and if you assign a value, > it's just a value, not a double-secret-probation reference. I don't > think it's a good idea to change this unless it can be done that way.
The current implementation of $r->pnotes(foo=>$x) is halfway similar to $r->pnotes->{foo}=\$x. Only halfway because fetching the value works as expected: $r->pnotes('foo'). In pure Perl the exact behavior cannot be expressed. Internally pnotes are stored in a HV. $r->pnotes without arguments returns a reference to that HV. Hence, $r->pnotes->{foo}=$o works as a normal assignment of a hash element: $ perl -MDevel::Peek -e '$x=1; Dump($x); $h{x}=$x; Dump(\%h);' SV = IV(0x816e598) at 0x816c6fc REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1 SV = RV(0x8178d48) at 0x8151d40 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x816c744 SV = PVHV(0x81699c8) at 0x816c744 ... Elt "x" HASH = 0x9303a5e5 SV = IV(0x816e59c) at 0x8151c20 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1 Note that the refcounts of both IVs the first after $x=1 and the second in %h are 1. Also the IVs themself are different objects one at 0x816e598 the second at 0x816e59c. With $r->pnotes->{x}=$x the output is similar. But with $r->pnotes(x=>$x) it changes: SV = IV(0x84c0664) at 0x866099c REFCNT = 1 FLAGS = (PADBUSY,PADMY,IOK,pIOK) IV = 1 SV = RV(0x8640b68) at 0x8651a7c REFCNT = 2 FLAGS = (TEMP,ROK) RV = 0x86397ec SV = PVHV(0x86453a0) at 0x86397ec ... Elt "x" HASH = 0x9303a5e5 SV = IV(0x84c0664) at 0x866099c REFCNT = 2 FLAGS = (PADBUSY,PADMY,IOK,pIOK) IV = 1 Now the both IVs are the same (0x84c0664) and the refcount after storing as a pnote is 2. And here is the problem. $r->pnotes->{x}=$x and $r->pnotes(x=>$x) are different operations. The first stores a copy of the IV represented by $x. The second stores the IV $x itself. This is somehow similar to *y=\$x: $ perl -e '$x=1; *y=\$x; $x++; print "$y\n";' 2 $ perl -MDevel::Peek -e '$x=1; Dump($x); *y=\$x; Dump($y);' SV = IV(0x816e590) at 0x816c6f4 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 1 SV = IV(0x816e590) at 0x816c6f4 REFCNT = 2 FLAGS = (IOK,pIOK) IV = 1 I think it is a bug even in MP1. Here the code that produces the output in error_log: package pn; use strict; use Apache2::RequestRec; use Apache2::RequestIO; use Apache2::RequestUtil; use Apache2::Const -compile=>'OK'; use Devel::Peek; sub handler { my $r=shift; my $x=1; Dump($x); $r->pnotes(x=>$x); Dump($r->pnotes); $r->print("ok\n"); return Apache2::Const::OK; } 1; Devel::Peek uses buffered output at C-level. Hence, you probably have to restart the server to see the actual output. Torsten
pgpXiWwBmTuqP.pgp
Description: PGP signature