diff options
author | Jarkko Hietaniemi <jhi@iki.fi> | 2003-08-31 08:55:59 +0000 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2003-08-31 08:55:59 +0000 |
commit | 67edfcd9ba9b6420b63d83f7bc5b3ddc4cd7e930 (patch) | |
tree | 457756066e51f16b48c3f37484dd13f75152cdd5 /lib/base.pm | |
parent | 036549e33639d565b91c920a89baa6a8d1be689e (diff) | |
download | perl-67edfcd9ba9b6420b63d83f7bc5b3ddc4cd7e930.tar.gz |
Ouch. Upgrading to base 2.0 made the threads tests very unhappy
both in blead and maint, lots of "Attempt to free non-existent
shared string" and "Unbalanced string table refcount" errors.
Retract #20960 (and #20963).
p4raw-id: //depot/perl@20965
Diffstat (limited to 'lib/base.pm')
-rw-r--r-- | lib/base.pm | 240 |
1 files changed, 57 insertions, 183 deletions
diff --git a/lib/base.pm b/lib/base.pm index e0cc4819ea..9b343987f9 100644 --- a/lib/base.pm +++ b/lib/base.pm @@ -1,171 +1,3 @@ -package base; - -use vars qw($VERSION); -$VERSION = '2.0'; - -# constant.pm is slow -sub SUCCESS () { 1 } - -sub PUBLIC () { 2**0 } -sub PRIVATE () { 2**1 } -sub INHERITED () { 2**2 } -sub PROTECTED () { 2**3 } - - -my $Fattr = \%fields::attr; - -sub has_fields { - my($base) = shift; - my $fglob = ${"$base\::"}{FIELDS}; - return $fglob && *$fglob{HASH}; -} - -sub has_version { - my($base) = shift; - my $vglob = ${$base.'::'}{VERSION}; - return $vglob && *$vglob{SCALAR}; -} - -sub has_attr { - my($proto) = shift; - my($class) = ref $proto || $proto; - return exists $Fattr->{$class}; -} - -sub get_attr { - $Fattr->{$_[0]} = [1] unless $Fattr->{$_[0]}; - return $Fattr->{$_[0]}; -} - -sub get_fields { - # Shut up a possible typo warning. - () = \%{$_[0].'::FIELDS'}; - - return \%{$_[0].'::FIELDS'}; -} - -sub show_fields { - my($base, $mask) = @_; - my $fields = \%{$base.'::FIELDS'}; - return grep { ($Fattr->{$base}[$fields->{$_}] & $mask) == $mask} - keys %$fields; -} - - -sub import { - my $class = shift; - - return SUCCESS unless @_; - - # List of base classes from which we will inherit %FIELDS. - my $fields_base; - - my $inheritor = caller(0); - - foreach my $base (@_) { - next if $inheritor->isa($base); - - if (has_version($base)) { - ${$base.'::VERSION'} = '-1, set by base.pm' - unless defined ${$base.'::VERSION'}; - } - else { - local $SIG{__DIE__} = 'IGNORE'; - eval "require $base"; - # Only ignore "Can't locate" errors from our eval require. - # Other fatal errors (syntax etc) must be reported. - die if $@ && $@ !~ /^Can't locate .*? at \(eval /; - unless (%{"$base\::"}) { - require Carp; - Carp::croak(<<ERROR); -Base class package "$base" is empty. - (Perhaps you need to 'use' the module which defines that package first.) -ERROR - - } - ${$base.'::VERSION'} = "-1, set by base.pm" - unless defined ${$base.'::VERSION'}; - } - push @{"$inheritor\::ISA"}, $base; - - # A simple test like (defined %{"$base\::FIELDS"}) will - # sometimes produce typo warnings because it would create - # the hash if it was not present before. - # - # We don't just check to see if the base in question has %FIELDS - # defined, we also check to see if it has -inheritable- fields. - # Its perfectly alright to inherit from multiple classes that have - # %FIELDS as long as only one of them has fields to give. - if ( has_fields($base) || has_attr($base) ) { - # Check to see if there are fields to be inherited. - if ( show_fields($base, PUBLIC) or - show_fields($base, PROTECTED) ) { - # No multiple fields inheritence *suck* - if ($fields_base) { - require Carp; - Carp::croak("Can't multiply inherit %FIELDS"); - } else { - $fields_base = $base; - } - } - } - } - - if( defined $fields_base ) { - inherit_fields($inheritor, $fields_base); - } -} - - -sub inherit_fields { - my($derived, $base) = @_; - - return SUCCESS unless $base; - - my $battr = get_attr($base); - my $dattr = get_attr($derived); - my $dfields = get_fields($derived); - my $bfields = get_fields($base); - - $dattr->[0] = @$battr; - - if( keys %$dfields ) { - warn "$derived is inheriting from $base but already has its own ". - "fields!\n". - "This will cause problems with pseudo-hashes.\n". - "Be sure you use base BEFORE declaring fields\n"; - } - - # Iterate through the base's fields adding all the non-private - # ones to the derived class. Hang on to the original attribute - # (Public, Private, etc...) and add Inherited. - # This is all too complicated to do efficiently with add_fields(). - while (my($k,$v) = each %$bfields) { - my $fno; - if ($fno = $dfields->{$k} and $fno != $v) { - require Carp; - Carp::croak ("Inherited %FIELDS can't override existing %FIELDS"); - } - - if( $battr->[$v] & PRIVATE ) { - $dattr->[$v] = undef; - } - else { - $dattr->[$v] = INHERITED | $battr->[$v]; - - # Derived fields must be kept in the same position as the - # base in order to make "static" typing work with psuedo-hashes. - # Alas, this kills multiple field inheritance. - $dfields->{$k} = $v; - } - } -} - - -1; - -__END__ - =head1 NAME base - Establish IS-A relationship with base class at compile time @@ -180,16 +12,15 @@ base - Establish IS-A relationship with base class at compile time Roughly similar in effect to BEGIN { - require Foo; - require Bar; - push @ISA, qw(Foo Bar); + require Foo; + require Bar; + push @ISA, qw(Foo Bar); } -Will also initialize the fields if one of the base classes has it. -Multiple Inheritence of fields is B<NOT> supported, if two or more -base classes each have inheritable fields the 'base' pragma will -croak. See L<fields>, L<public> and L<protected> for a description of -this feature. +Will also initialize the %FIELDS hash if one of the base classes has +it. Multiple inheritance of %FIELDS is not supported. The 'base' +pragma will croak if multiple base classes have a %FIELDS hash. See +L<fields> for a description of this feature. When strict 'vars' is in scope, I<base> also lets you assign to @ISA without having to declare @ISA with the 'vars' pragma first. @@ -201,20 +32,63 @@ $VERSION in the base package. If $VERSION is not detected even after loading it, I<base> will define $VERSION in the base package, setting it to the string C<-1, set by base.pm>. - =head1 HISTORY This module was introduced with Perl 5.004_04. +=head1 SEE ALSO + +L<fields> -=head1 CAVEATS +=cut -Due to the limitations of the pseudo-hash implementation, you must use -base I<before> you declare any of your own fields. +package base; +use 5.006_001; +our $VERSION = "1.04"; -=head1 SEE ALSO +sub import { + my $class = shift; + my $fields_base; + my $pkg = caller(0); -L<fields> + foreach my $base (@_) { + next if $pkg->isa($base); + my $vglob; + if ($vglob = ${"$base\::"}{VERSION} and *$vglob{SCALAR}) { + $$vglob = "-1, set by base.pm" unless defined $$vglob; + } else { + eval "require $base"; + # Only ignore "Can't locate" errors from our eval require. + # Other fatal errors (syntax etc) must be reported. + die if $@ && $@ !~ /^Can't locate .*? at \(eval /; + unless (%{"$base\::"}) { + require Carp; + Carp::croak("Base class package \"$base\" is empty.\n", + "\t(Perhaps you need to 'use' the module ", + "which defines that package first.)"); + } + ${"$base\::VERSION"} = "-1, set by base.pm" unless defined ${"$base\::VERSION"}; + } + push @{"$pkg\::ISA"}, $base; + + # A simple test like (defined %{"$base\::FIELDS"}) will + # sometimes produce typo warnings because it would create + # the hash if it was not present before. + my $fglob; + if ($fglob = ${"$base\::"}{"FIELDS"} and *$fglob{HASH}) { + if ($fields_base) { + require Carp; + Carp::croak("Can't multiply inherit %FIELDS"); + } else { + $fields_base = $base; + } + } + } + if ($fields_base) { + require fields; + fields::inherit($pkg, $fields_base); + } +} -=cut +1; |