X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema.pm;h=8270c27425ba2f619a35c9c109099980eb352425;hb=50261284a5486d1974adb202eb84e5ed782d3665;hp=77a7fe7e511d1eba2d9e71b20309f1949c7879b1;hpb=c3e9f7189094e94137356251c4f0b1f1cbfeb04a;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 77a7fe7..8270c27 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -11,6 +11,7 @@ use File::Spec; use Sub::Name 'subname'; use Module::Find(); use Storable(); +use B qw/svref_2object/; use namespace::clean; use base qw/DBIx::Class/; @@ -244,7 +245,9 @@ sub load_namespaces { use warnings 'redefine'; # ensure classes are loaded and attached in inheritance order - $class->ensure_class_loaded($_) foreach(values %results); + for my $res (values %results) { + $class->ensure_class_loaded($res); + } my %inh_idx; my @subclass_last = sort { @@ -898,6 +901,7 @@ sub compose_namespace { my $schema = $self->clone; { no warnings qw/redefine/; + no strict qw/refs/; # local *Class::C3::reinitialize = sub { }; foreach my $moniker ($schema->sources) { my $source = $schema->source($moniker); @@ -906,8 +910,14 @@ sub compose_namespace { $target_class => $source->result_class, ($base ? $base : ()) ); $source->result_class($target_class); - $target_class->result_source_instance($source) - if $target_class->can('result_source_instance'); + if ($target_class->can('result_source_instance')) { + + # since the newly created classes are registered only with + # the instance of $schema, it should be safe to weaken + # the ref (it will GC when $schema is destroyed) + $target_class->result_source_instance($source); + weaken ${"${target_class}::__cag_result_source_instance"}; + } $schema->register_source($moniker, $source); } } @@ -1192,13 +1202,13 @@ sub thaw { =head2 freeze -This doesn't actually do anything more than call L, it is just +This doesn't actually do anything more than call L, it is just provided here for symmetry. =cut sub freeze { - return Storable::freeze($_[1]); + return Storable::nfreeze($_[1]); } =head2 dclone @@ -1363,6 +1373,29 @@ sub _register_source { $self->class_mappings(\%map); } +{ + my $global_phase_destroy; + + END { $global_phase_destroy++ } + + sub DESTROY { + return if $global_phase_destroy; + + my $self = shift; + my $srcs = $self->source_registrations; + + for my $moniker (keys %$srcs) { + # find first source that is not about to be GCed (someone other than $self + # holds a reference to it) and reattach to it, weakening our own link + if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) { + $srcs->{$moniker}->schema($self); + weaken $srcs->{$moniker}; + last; + } + } + } +} + sub _unregister_source { my ($self, $moniker) = @_; my %reg = %{$self->source_registrations};