package VCP::RefCountedFile; =head1 NAME VCP::RefCountedFile - An object that deletes a named file when nothing refers to it any more. =head1 SYNOPSIS use VCP::RefCountedFile; { my $fn = VCP::RefCountedFile->new( "/path/to/name" ); print $fn; } ## "name" is deleted here. =head1 DESCRIPTION An object that mimics a string, but which refers to a file and deletes the file when the last reference to the file via such objects disappears. =cut $VERSION = 1; use strict ; use Carp ; use overload ( '""' => \&as_string, 'cmp' => sub { "$_[0]" cmp "$_[1]" }, ); use VCP::Debug ':debug' ; use VCP::Logger qw( pr ); use VCP::Utils 'empty' ; sub new { my $class = ref $_[0] ? ref shift : shift; my $self = bless \my( $value ), $class; $self->set( @_ ) if @_; return $self; } sub as_string { my $self = shift; return $$self; } my %ref_counts; ## Each file gets a ref count. This hash maintains that ref_count. sub set { my $self = shift; my ( $value ) = @_; if ( !empty( $$self ) ) { my $fn = "$$self"; ## for simplicity if ( $ref_counts{$fn} && --$ref_counts{$fn} < 1 && -e $fn ) { if ( debugging ) { my @details ; my $i = 2 ; do { @details = caller($i++) } until $details[0] ne __PACKAGE__ ; debug "$self unlinking '$fn' in " . join( '|', @details[0,1,2,3]) ; } unlink $fn or pr "$! unlinking $fn\n" } } $$self = $value; ++$ref_counts{$$self} unless empty $$self; } END { if ( debugging && ! $ENV{VCPNODELETE} ) { for ( sort keys %ref_counts ) { if ( -e $_ ) { pr "$_ not deleted" ; } } } } sub DESTROY { return if $ENV{VCPNODELETE}; my $self = shift ; $self->set( undef ); } =back =head1 SUBCLASSING This class is a bless scalar. =head1 COPYRIGHT Copyright 2000, Perforce Software, Inc. All Rights Reserved. This module and the VCP package are licensed according to the terms given in the file LICENSE accompanying this distribution, a copy of which is included in L. =head1 AUTHOR Barrie Slaymaker =cut 1