use mro::get_isarev if available
Yuval Kogman [Sat, 9 Aug 2008 05:17:58 +0000 (05:17 +0000)]
lib/Class/MOP.pm
lib/Class/MOP/Class.pm

index efa1166..4af7900 100644 (file)
@@ -24,6 +24,10 @@ BEGIN {
         ? sub () { 0 }
         : sub () { 1 };    
 
+    *HAVE_ISAREV = defined(&mro::get_isarev)
+        ? sub () { 1 }
+        : sub () { 1 };
+
     # NOTE:
     # we may not use this yet, but once 
     # the get_code_info XS gets merged 
@@ -972,6 +976,11 @@ We set this constant depending on what version perl we are on, this
 allows us to take advantage of new 5.10 features and stay backwards 
 compat.
 
+=item I<HAVE_ISAREV>
+
+Whether or not C<mro> provides C<get_isarev>, a much faster way to get all the
+subclasses of a certain class.
+
 =back
 
 =head2 Utility functions
index f517a56..b8834a6 100644 (file)
@@ -496,44 +496,49 @@ sub subclasses {
     my $self = shift;
 
     my $super_class = $self->name;
-    my @derived_classes;
-    
-    my $find_derived_classes;
-    $find_derived_classes = sub {
-        my ($outer_class) = @_;
 
-        my $symbol_table_hashref = do { no strict 'refs'; \%{"${outer_class}::"} };
+    if ( Class::MOP::HAVE_ISAREV() ) {
+        return @{ $super_class->mro::get_isarev() };
+    } else {
+        my @derived_classes;
 
-        SYMBOL:
-        for my $symbol ( keys %$symbol_table_hashref ) {
-            next SYMBOL if $symbol !~ /\A (\w+):: \z/x;
-            my $inner_class = $1;
+        my $find_derived_classes;
+        $find_derived_classes = sub {
+            my ($outer_class) = @_;
 
-            next SYMBOL if $inner_class eq 'SUPER';    # skip '*::SUPER'
+            my $symbol_table_hashref = do { no strict 'refs'; \%{"${outer_class}::"} };
 
-            my $class =
-              $outer_class
-              ? "${outer_class}::$inner_class"
-              : $inner_class;
+            SYMBOL:
+            for my $symbol ( keys %$symbol_table_hashref ) {
+                next SYMBOL if $symbol !~ /\A (\w+):: \z/x;
+                my $inner_class = $1;
 
-            if ( $class->isa($super_class) and $class ne $super_class ) {
-                push @derived_classes, $class;
-            }
+                next SYMBOL if $inner_class eq 'SUPER';    # skip '*::SUPER'
 
-            next SYMBOL if $class eq 'main';           # skip 'main::*'
+                my $class =
+                $outer_class
+                ? "${outer_class}::$inner_class"
+                : $inner_class;
 
-            $find_derived_classes->($class);
-        }
-    };
+                if ( $class->isa($super_class) and $class ne $super_class ) {
+                    push @derived_classes, $class;
+                }
 
-    my $root_class = q{};
-    $find_derived_classes->($root_class);
+                next SYMBOL if $class eq 'main';           # skip 'main::*'
 
-    undef $find_derived_classes;
+                $find_derived_classes->($class);
+            }
+        };
+
+        my $root_class = q{};
+        $find_derived_classes->($root_class);
 
-    @derived_classes = sort { $a->isa($b) ? 1 : $b->isa($a) ? -1 : 0 } @derived_classes;
+        undef $find_derived_classes;
 
-    return @derived_classes;
+        @derived_classes = sort { $a->isa($b) ? 1 : $b->isa($a) ? -1 : 0 } @derived_classes;
+
+        return @derived_classes;
+    }
 }