Revision history for Perl extension Class::C3.
+0.14 XXX Not Yet Released
+ - Fix for rt.cpan.org #21558
+
0.13 Fri. Aug 25, 2006
- Make use of Algorithm::C3 0.05's merge caching
use Scalar::Util 'blessed';
use Algorithm::C3;
-our $VERSION = '0.13';
+our $VERSION = '0.14';
# this is our global stash of both
# MRO's and method dispatch tables
# use these for debugging ...
sub _dump_MRO_table { %MRO }
our $TURN_OFF_C3 = 0;
+our $_initialized = 0;
sub import {
my $class = caller();
sub initialize {
# why bother if we don't have anything ...
return unless keys %MRO;
+ if($_initialized) {
+ uninitialize();
+ $MRO{$_} = undef foreach keys %MRO;
+ }
_calculate_method_dispatch_tables();
_apply_method_dispatch_tables();
%next::METHOD_CACHE = ();
+ $_initialized = 1;
}
sub uninitialize {
return unless keys %MRO;
_remove_method_dispatch_tables();
%next::METHOD_CACHE = ();
+ $_initialized = 0;
}
-sub reinitialize {
- uninitialize();
- # clean up the %MRO before we re-initialize
- $MRO{$_} = undef foreach keys %MRO;
- initialize();
-}
+sub reinitialize { goto &initialize }
## functions for applying C3 to classes
your own INIT method which calls this function.
NOTE:
-This can B<not> be used to re-load the dispatch tables for all classes. Use C<reinitialize> for that.
+
+If C<initialize> detects that C<initialize> has already been executed, it will L</uninitialize> and
+clear the MRO cache first.
=item B<uninitialize>
=item B<reinitialize>
-This effectively calls C<uninitialize> followed by C<initialize> the result of which is a reloading of
-B<all> the calculated C3 dispatch tables.
-
-It should be noted that if you have a large class library, this could potentially be a rather costly
-operation.
+This is an alias for L</initialize> above.
=back
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+BEGIN {
+ use_ok('Class::C3');
+}
+
+=pod
+
+rt.cpan.org # 21558
+
+If compile-time code from another module issues a [re]initialize() part-way
+through the process of setting up own our modules, that shouldn't prevent
+our own initialize() call from working properly.
+
+=cut
+
+{
+ package TestMRO::A;
+ use Class::C3;
+ sub testmethod { 42 }
+
+ package TestMRO::B;
+ use base 'TestMRO::A';
+ use Class::C3;
+
+ package TestMRO::C;
+ use base 'TestMRO::A';
+ use Class::C3;
+ sub testmethod { shift->next::method + 1 }
+
+ package TestMRO::D;
+ BEGIN { Class::C3::initialize }
+ use base 'TestMRO::B';
+ use base 'TestMRO::C';
+ use Class::C3;
+ sub new {
+ my $class = shift;
+ my $self = {};
+ bless $self => $class;
+ }
+}
+
+Class::C3::initialize;
+is(TestMRO::D->new->testmethod, 43, 'double-initialize works ok');