deferred
view release on metacpan or search on metacpan
lib/deferred.pm view on Meta::CPAN
package deferred;
use strict;
our $VERSION = "0.01";
# Modules the user has requested to defer
my @enabled;
# Modules we've half loaded
my %half_loaded;
sub import {
my $class = shift;
push @enabled, map { ref $_ ? $_ : qr/^$_$/ } @_;
}
sub unimport {
my $class = shift;
my $discard = @_ && $_[0] eq '-discard' ? pop : 0;
if(@_) {
my @disable = map { ref $_ ? $_ : qr/^$_$/ } @_;
for my $disable(@disable) {
@enabled = grep { $_ ne $disable } @enabled;
}
} else {
@enabled = ();
if(!$discard) {
for my $class(keys %half_loaded) {
_load($class);
}
}
%half_loaded = ();
}
}
unshift @INC, my $inc_ref = sub {
my(undef, $file) = @_;
# We get a filename here, we let the user specify a module name, so convert
# it back.
(my $module = $file) =~ s{/}{::}g;
$module =~ s/\.pm$//;
if(caller =~ /^(?:base|parent)/) {
# When these modules load something they really do mean it
return;
}
for my $enabled(@enabled) {
if($module =~ $enabled) {
$half_loaded{$module} = join ":", (caller)[1,2];
open my $fh, "<", \"1";
return $fh;
}
}
return;
};
sub UNIVERSAL::AUTOLOAD {
my $load = $UNIVERSAL::AUTOLOAD;
my($class, $method) = ($load =~ /^(.*)::(.*)$/);
return if $method eq 'DESTROY';
_load($class) if exists $half_loaded{$class};
no warnings 'once';
no strict 'refs';
if(*{$load}{CODE}) {
goto &$load;
} elsif(my $can = $class->can($method)) {
goto &$can;
} else {
# Really doesn't exist
require Carp;
Carp::croak("Undefined subroutine/method called ($load)");
}
}
sub _load {
my $class = shift;
# Avoid the need to reimplement @INC searching
local @INC = grep { !ref || $_ != $inc_ref } @INC;
(my $file = $class) =~ s{::}{/}g;
$file .= ".pm";
local %INC = %INC;
delete $INC{$file};
my $orig = delete $half_loaded{$class};
my $ok = eval { require $file };
die "deferred load of $class failed (originally loaded at $orig):\n$@"
if !$ok;
$ok;
}
1;
__END__
=head1 NAME
deferred - Defer loading of modules until methods are called
=head1 SYNOPSIS
( run in 1.883 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )