Centralize handling of refcount in DBIC::_Util
Peter Rabbitson [Sun, 12 Jan 2014 12:36:30 +0000 (13:36 +0100)]
lib/DBIx/Class/Schema.pm
lib/DBIx/Class/_Util.pm
t/lib/DBICTest/Util/LeakTracer.pm

index 76395ae..4c3cce5 100644 (file)
@@ -8,8 +8,8 @@ use base 'DBIx::Class';
 use DBIx::Class::Carp;
 use Try::Tiny;
 use Scalar::Util qw/weaken blessed/;
+use DBIx::Class::_Util 'refcount';
 use Sub::Name 'subname';
-use B 'svref_2object';
 use Devel::GlobalDestruction;
 use namespace::clean;
 
@@ -1405,7 +1405,7 @@ sub DESTROY {
     # which will serve as a signal to not try doing anything else
     # however beware - on older perls the exception seems randomly untrappable
     # due to some weird race condition during thread joining :(((
-    if (ref $srcs->{$source_name} and svref_2object($srcs->{$source_name})->REFCNT > 1) {
+    if (length ref $srcs->{$source_name} and refcount($srcs->{$source_name}) > 1) {
       local $@;
       eval {
         $srcs->{$source_name}->schema($self);
index cf7443f..0afe2ea 100644 (file)
@@ -53,7 +53,7 @@ use Carp;
 use Scalar::Util qw(refaddr weaken);
 
 use base 'Exporter';
-our @EXPORT_OK = qw(sigwarn_silencer modver_gt_or_eq fail_on_internal_wantarray);
+our @EXPORT_OK = qw(sigwarn_silencer modver_gt_or_eq fail_on_internal_wantarray refcount);
 
 sub sigwarn_silencer {
   my $pattern = shift;
@@ -65,6 +65,15 @@ sub sigwarn_silencer {
   return sub { &$orig_sig_warn unless $_[0] =~ $pattern };
 }
 
+sub refcount {
+  croak "Expecting a reference" if ! length ref $_[0];
+
+  require B;
+  # No tempvars - must operate on $_[0], otherwise the pad
+  # will count as an extra ref
+  B::svref_2object($_[0])->REFCNT;
+}
+
 sub modver_gt_or_eq {
   my ($mod, $ver) = @_;
 
index 2c10000..8320efe 100644 (file)
@@ -5,7 +5,7 @@ use strict;
 
 use Carp;
 use Scalar::Util qw/isweak weaken blessed reftype refaddr/;
-use B 'svref_2object';
+use DBIx::Class::_Util 'refcount';
 use DBICTest::Util 'stacktrace';
 
 use base 'Exporter';
@@ -142,10 +142,8 @@ sub assert_empty_weakregistry {
           and
         my $expected_refcnt = $classdata_refcounts->{$weak_registry->{$slot}{refaddr}}
       ) {
-        # need to store the SVref and examine it separately,
-        # to push the weakref instance off the pad
-        my $sv = svref_2object($weak_registry->{$slot}{weakref});
-        delete $weak_registry->{$slot} if $sv->REFCNT == $expected_refcnt;
+        delete $weak_registry->{$slot}
+          if refcount($weak_registry->{$slot}{weakref}) == $expected_refcnt;
       }
     }
   }