Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Class DBI and reference counting

by Nomis52 (Friar)
on Jan 10, 2006 at 22:52 UTC ( [id://522339]=perlquestion: print w/replies, xml ) Need Help??

Nomis52 has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks, I'm using Class::DBI with two classes, A and B with A having many Bs. The database is set up like so:
mysql> select * from test_a;
+-----+
| oid |
+-----+
|   1 |
+-----+

mysql> select * from test_b;
+-----+------+------+
| oid | aoid | flag |
+-----+------+------+
|   1 |    1 |    0 |
|   2 |    1 |    0 |
|   3 |    1 |    1 |
+-----+------+------+
3 rows in set (0.01 sec)
Where aoid references and oid in test_a .

Below is the code for the two classes

Testing2.pm

use strict; use warnings ; package Testing2; use base 'Testing'; Testing2->table('test_a'); Testing2->columns(Primary => qw/oid/ ) ; Testing2->has_many( bs => 'Testing3', 'aoid'); sub flagged { my $self =shift ; my @bs = $self->bs( flag => 1 ) ; return shift @bs ; } sub flagged2 { my $self =shift ; unless(defined($self->{f})) { my @bs = $self->bs( flag => 1 ) ; $self->{f} = shift @bs ; } return $self->{f} ; } sub DESTROY { my $self = shift; print "Destroying a " . $self->oid . "\n"; } 1;

Testing3.pm

use strict; use warnings ; package Testing3; use base 'Testing'; Testing3->table('test_b'); Testing3->columns(Primary => qw/oid/ ) ; Testing3->columns(Essential => qw/aoid flag/ ) ; Testing3->has_a( aoid => 'Testing2'); sub DESTROY { my $self = shift; print STDERR "Destroying b " . $self->oid . "\n"; } 1;
Now I need to be able to find the particular B that corrosponds to a particular A where flag is 1. So in class A I have:
sub flagged { my $self =shift ; my @bs = $self->bs( flag => 1 ) ; return shift @bs ; }
But in my code, flagged is called many times per execution and I'd really like to be able to cache the results of the search so it's only performed once. I tried the following:
sub flagged2 { my $self =shift ; unless(defined($self->{f})) { my @bs = $self->bs( flag => 1 ) ; $self->{f} = shift @bs ; } return $self->{f} ; }
The problem is now that the objects a and b no longer get destroyed when the execution finishes because the reference count never hits 0. This is causing problems under mod_perl.

Is there a way to ensure the objects get destroyed or alternatively a better way to do this ?

Cheers, Simon N

Replies are listed 'Best First'.
Re: Class DBI and reference counting
by chromatic (Archbishop) on Jan 10, 2006 at 23:07 UTC

    If you're using a modern enough Perl (5.6.1 or later, I believe), use Scalar::Util's weaken() function to create weak references in your cache. The documentation for the function shows a similar application.

      I acutally tried weaken before posting:
      sub flagged2 { my $self =shift ; unless(defined($self->{f})) { my @bs = $self->bs( flag => 1 ) ; $self->{f} = weaken(shift @bs) ; } return $self->{f} ; }
      The problem is on the first call to the function it works as expected, but the second time it's called the object has already gone out of scope and been destroyed resulting in an undefined value returned.
Re: Class DBI and reference counting
by perrin (Chancellor) on Jan 10, 2006 at 23:20 UTC
    Since you're using mod_perl, you can store them in Apache->request->pnotes(). See the pnotes() method in the mod_perl docs.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://522339]
Approved by chromatic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-03-28 15:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found