SVN: toys/rsget.pl/RSGet/MortalObject.pm
sparky
sparky at pld-linux.org
Fri Oct 9 23:22:33 CEST 2009
Author: sparky
Date: Fri Oct 9 23:22:33 2009
New Revision: 10745
Added:
toys/rsget.pl/RSGet/MortalObject.pm
Log:
- new, object killer, used to prevent memory leaks
Added: toys/rsget.pl/RSGet/MortalObject.pm
==============================================================================
--- (empty file)
+++ toys/rsget.pl/RSGet/MortalObject.pm Fri Oct 9 23:22:33 2009
@@ -0,0 +1,110 @@
+package RSGet::MortalObject;
+
+use strict;
+use warnings;
+use RSGet::Tools;
+set_rev qq$Id: Wait.pm 10652 2009-10-02 15:28:26Z sparky $;
+
+# This is object holder, which will destroy the object if it doesn't
+# receive heartbeat for some amount of time. It is used to prevent leaking
+# memory, expecially in http interface.
+
+my %holders;
+my $last_id = 0;
+
+sub new
+{
+ my $class = shift;
+ my $obj = shift;
+ my %opts = @_;
+
+ my $time = time;
+
+ my $id = sprintf "%d_%.6x", ++$last_id, int rand 1 << 24;
+
+ my $holder = {
+ obj => $obj,
+ start => $time,
+ last => $time,
+ die_after => $opts{die_after} || 10,
+ };
+ $holder->{kill_after} = $time + $opts{kill_after} if $opts{kill_after};
+ $holders{ $id } = $holder;
+
+ my $self = \$id;
+ bless $self, $class;
+
+ return $self;
+}
+
+sub from_id
+{
+ my $class = shift;
+ my $id = shift;
+
+ return undef unless exists $holders{ $id };
+ my $self = \$id;
+ bless $self, $class;
+ return $self;
+}
+
+sub obj
+{
+ my $self = shift;
+ my $id = $$self;
+
+ my $h = $holders{ $id } or return undef;
+ $h->{last} = time;
+ return $h->{obj};
+}
+
+sub id
+{
+ my $self = shift;
+ my $id = $$self;
+
+ return undef unless $holders{ $id };
+ return $id;
+}
+
+sub time_to_kill
+{
+ my $self = shift;
+ my $id = $$self;
+
+ my $h = $holders{ $id } or return undef;
+ return undef unless $h->{kill_after};
+ return $h->{kill_after} - time;
+}
+
+sub heartbeat
+{
+ my $self = shift;
+ my $id = $$self;
+
+ my $h = $holders{ $id } or return undef;
+ $h->{last} = time;
+
+ return 1;
+}
+
+sub update
+{
+ my $time = time;
+
+ foreach my $id ( keys %holders ) {
+ my $h = $holders{ $id };
+ if ( $h->{last} + $h->{die_after} < $time ) {
+ p "Mortal $id died\n" if verbose( 4 );
+ delete $h->{obj};
+ delete $holders{ $id };
+ } elsif ( $h->{kill_after} and $h->{kill_after} < $time ) {
+ p "Mortal $id killed\n" if verbose( 4 );
+ delete $h->{obj};
+ delete $holders{ $id };
+ }
+ }
+ RSGet::Line::status( 'mortals' => scalar keys %holders );
+}
+
+1;
More information about the pld-cvs-commit
mailing list