Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
Welcome to the Monastery
 
PerlMonks  

Class DBI and reference counting

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

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.

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 18: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 18: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
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.