No, krisahoch, he can return the database handle and modify %{$self} as a side effect...
Mark, is $self properly blessed into the package? Otherwise, DESTROY would never be called...
It could also be the global cleanup order problem mentioned in this thread.
Have you tried using this class only from a subroutine? Take the part of the code at the top level that uses this class, and wrap it in a sub. Then put
$|=1; # make sure we see printouts and warns in order
print "Before sub\n";
subThatUsesClass();
print "After sub, I _better_ have seen DESTROY happen...\n";
If it's the random global cleanups causing the problem,
having your variable as a lexical in the sub should get it cleaned up properly...
--
Mike
Edit: Put in correct link to tilly's excellent description of the global cleanup problem... | [reply] [d/l] |
Hi Mike,
Yes, of course I bless my object.
I even tried this, but I think it is the same as
during the exit.
my $o=new MyClass;
my $dbh=$o->opendb;
warn $o->{_dbh};
warn $dbh; # the same as the previous line
undef $o;
exit;
I cannot put it as a lexical in the sub because
I have just written an entire framework (+5000 lines),
consisting of a tree of packages
in OO, and setting the DBI object as an attribute
has an advantage of using persistant DB connections.
This is the actual opendb routine
sub opendb {
my $self=shift;
local($@);
if ( not $self->{_dbh} or not $self->{_dbh}->ping) {
eval{ $self->{_dbh}=$self->{_dbi}->connect() ; } ;
if ( $@ ) {
$self->Log('!',$@) and die "db gives error" ;
}
}
$self->{_dbh}->{LongReadLen}=100000; # to handle Long column types
$self->{_dbh}->{LongTruncOk}=0; # generates an error when the dat
+a is too long
$self->{_dbh}->{AutoCommit}=0; # Lets run transactional
return $self->{_dbh};
}
And I call this opendb as much as I like, without
going to the db everytime.
(note $self->{_dbi} is a object from my superclass of
DBI).
And the link to tilly's one, that was the one I
was referring to, but using flyweightwrapper is
a bit overshooting, I think.
---------------------------
Dr. Mark Ceulemans
Senior Consultant
IT Masters, Belgium
| [reply] [d/l] [select] |
(Edit: I don't believe _dbh goes away before $self does, I think DBI is unloaded before the global cleanup happens; that's why I'm suggesting this END{} fix...)
Hmmm, you don't need the total encapsulation features of the FlyweightWrapper, either...
I'm betting packages get unloaded correctly. What happens if you add a hash at the package level in your class called instances, and do this:
# private hash of instances
my %instances;
#...
sub new {
# ... build up $self, bless it, do whatever
$instances{$self}=1;
# ... whatever else you need to do...
}
#...
sub DESTROY {
# don't double-destroy
return unless $instances{$self};
#... do whatever
$instances{$self}=0;
}
END {
foreach my $instance(keys %instances) {
$instance->DESTROY() if $instances{$instance};
}
}
Offhand, I can't remember whether calling DESTROY directly is ok or not, but if not, you could get the same effect with a helper sub that DESTROY calls.
--
Mike
Edit: I forgot to check $instances{$self}
at the top of DESTROY | [reply] [d/l] |