1 package Class::Accessor::Grouped;
6 use Module::Runtime ();
9 # use M::R to work around the 5.8 require bugs
11 Module::Runtime::require_module('MRO::Compat');
18 our $VERSION = '0.10010';
19 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
21 # when changing minimum version don't forget to adjust Makefile.PL as well
22 our $__minimum_xsa_version;
23 BEGIN { $__minimum_xsa_version = '1.15' }
26 # the unless defined is here so that we can override the value
27 # before require/use, *regardless* of the state of $ENV{CAG_USE_XS}
28 $USE_XS = $ENV{CAG_USE_XS}
29 unless defined $USE_XS;
32 package # hide from PAUSE
35 die "Huh?! No minimum C::XSA version?!\n"
36 unless $__minimum_xsa_version;
41 # individual (one const at a time) imports so we are 5.6.2 compatible
42 # if we can - why not ;)
43 constant->import( NO_SUBNAME => eval {
44 Module::Runtime::require_module('Sub::Name')
48 constant->import( NO_CXSA => ( NO_SUBNAME() || ( eval {
49 Module::Runtime::require_module('Class::XSAccessor');
50 $found_cxsa = Class::XSAccessor->VERSION;
51 Class::XSAccessor->VERSION($__minimum_xsa_version);
54 if (NO_CXSA() and $found_cxsa and !$ENV{CAG_OLD_XS_NOWARN}) {
56 'The installed version of Class::XSAccessor is too old '
57 . "(v$found_cxsa < v$__minimum_xsa_version). Please upgrade "
58 . "to instantly quadruple the performance of 'simple' accessors. "
59 . 'Set $ENV{CAG_OLD_XS_NOWARN} if you wish to disable this '
64 constant->import( BROKEN_GOTO => ($] < '5.008009') ? 1 : 0 );
66 constant->import( UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0 );
68 constant->import( TRACK_UNDEFER_FAIL => (
69 $INC{'Test/Builder.pm'} || $INC{'Test/Builder2.pm'}
71 $0 =~ m{ ^ (?: \. \/ )? x?t / .+ \.t $}x
74 sub perlstring ($) { q{"}. quotemeta( shift ). q{"} };
77 # Yes this method is undocumented
78 # Yes it should be a private coderef like all the rest at the end of this file
79 # No we can't do that (yet) because the DBIC-CDBI compat layer overrides it
82 my $illegal_accessors_warned;
83 sub _mk_group_accessors {
84 my($self, $maker, $group, @fields) = @_;
85 my $class = length (ref ($self) ) ? ref ($self) : $self;
88 no warnings 'redefine';
90 # So we don't have to do lots of lookups inside the loop.
91 $maker = $self->can($maker) unless ref $maker;
95 my ($name, $field) = (ref $_) ? (@$_) : ($_, $_);
97 if ($name !~ /\A[A-Z_a-z][0-9A-Z_a-z]*\z/) {
101 "Illegal accessor name %s - nulls should never appear in stash keys",
102 __CAG_ENV__::perlstring($name),
105 elsif (! $ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK} ) {
107 "Illegal accessor name '$name'. If you want CAG to attempt creating "
108 . 'it anyway (possible if Sub::Name is available) set '
109 . '$ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK}'
112 elsif (__CAG_ENV__::NO_SUBNAME) {
114 "Unable to install accessor with illegal name '$name': "
115 . 'Sub::Name not available'
119 # Because one of the former maintainers of DBIC::SL is a raging
120 # idiot, there is now a ton of DBIC code out there that attempts
121 # to create column accessors with illegal names. In the interest
122 # of not cluttering the logs of unsuspecting victims (unsuspecting
123 # because these accessors are unusuable anyway) we provide an
124 # explicit "do not warn at all" escape, until all such code is
125 # fixed (this will be a loooooong time >:(
126 $ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK} ne 'DO_NOT_WARN'
128 ! $illegal_accessors_warned->{$class}++
131 "Installing illegal accessor '$name' into $class, see "
132 . 'documentation for more details'
137 Carp::carp("Having a data accessor named '$name' in '$class' is unwise.")
138 if $name =~ /\A(?: DESTROY | AUTOLOAD | CLONE )\z/x;
140 my $alias = "_${name}_accessor";
142 for ($name, $alias) {
144 # the maker may elect to not return anything, meaning it already
145 # installed the coderef for us (e.g. lack of Sub::Name)
146 my $cref = $self->$maker($group, $field, $_)
149 my $fq_meth = "${class}::$_";
151 *$fq_meth = Sub::Name::subname($fq_meth, $cref);
152 #unless defined &{$class."\:\:$field"}
157 # $gen_accessor coderef is setup at the end for clarity
162 Class::Accessor::Grouped - Lets you build groups of accessors
166 use base 'Class::Accessor::Grouped';
168 # make basic accessors for objects
169 __PACKAGE__->mk_group_accessors(simple => qw(id name email));
171 # make accessor that works for objects and classes
172 __PACKAGE__->mk_group_accessors(inherited => 'awesome_level');
174 # make an accessor which calls a custom pair of getters/setters
175 sub get_column { ... this will be called when you do $obj->name() ... }
176 sub set_column { ... this will be called when you do $obj->name('foo') ... }
177 __PACKAGE__->mk_group_accessors(column => 'name');
181 This class lets you build groups of accessors that will call different
182 getters and setters. The documentation of this module still requires a lot
183 of work (B<< volunteers welcome >.> >>), but in the meantime you can refer to
184 L<this post|http://lo-f.at/glahn/2009/08/WritingPowerfulAccessorsForPerlClasses.html>
185 for more information.
187 =head2 Notes on accessor names
189 In general method names in Perl are considered identifiers, and as such need to
190 conform to the identifier specification of C<qr/\A[A-Z_a-z][0-9A-Z_a-z]*\z/>.
191 While it is rather easy to invoke methods with non-standard names
192 (C<< $obj->${\"anything goes"} >>), it is not possible to properly declare such
193 methods without the use of L<Sub::Name>. Since this module must be able to
194 function identically with and without its optional dependencies, starting with
195 version C<0.10008> attempting to declare an accessor with a non-standard name
196 is a fatal error (such operations would silently succeed since version
197 C<0.08004>, as long as L<Sub::Name> is present, or otherwise would result in a
198 syntax error during a string eval).
200 Unfortunately in the years since C<0.08004> a rather large body of code
201 accumulated in the wild that does attempt to declare accessors with funny
202 names. One notable perpetrator is L<DBIx::Class::Schema::Loader>, which under
203 certain conditions could create accessors of the C<column> group which start
204 with numbers and/or some other punctuation (the proper way would be to declare
205 columns with the C<accessor> attribute set to C<undef>).
207 Therefore an escape mechanism is provided via the environment variable
208 C<CAG_ILLEGAL_ACCESSOR_NAME_OK>. When set to a true value, one warning is
209 issued B<per class> on attempts to declare an accessor with a non-conforming
210 name, and as long as L<Sub::Name> is available all accessors will be properly
211 created. Regardless of this setting, accessor names containing nulls C<"\0">
212 are disallowed, due to various deficiencies in perl itself.
214 If your code base has too many instances of illegal accessor declarations, and
215 a fix is not feasible due to time constraints, it is possible to disable the
216 warnings altogether by setting C<$ENV{CAG_ILLEGAL_ACCESSOR_NAME_OK}> to
217 C<DO_NOT_WARN> (observe capitalization).
221 =head2 mk_group_accessors
223 __PACKAGE__->mk_group_accessors(simple => 'hair_length', [ hair_color => 'hc' ]);
227 =item Arguments: $group, @fieldspec
233 Creates a set of accessors in a given group.
235 $group is the name of the accessor group for the generated accessors; they
236 will call get_$group($field) on get and set_$group($field, $value) on set.
238 If you want to mimic Class::Accessor's mk_accessors $group has to be 'simple'
239 to tell Class::Accessor::Grouped to use its own get_simple and set_simple
242 @fieldspec is a list of field/accessor names; if a fieldspec is a scalar
243 this is used as both field and accessor name, if a listref it is expected to
244 be of the form [ $accessor, $field ].
248 sub mk_group_accessors {
249 my ($self, $group, @fields) = @_;
251 $self->_mk_group_accessors('make_group_accessor', $group, @fields);
255 =head2 mk_group_ro_accessors
257 __PACKAGE__->mk_group_ro_accessors(simple => 'birthdate', [ social_security_number => 'ssn' ]);
261 =item Arguments: $group, @fieldspec
267 Creates a set of read only accessors in a given group. Identical to
268 L</mk_group_accessors> but accessors will throw an error if passed a value
269 rather than setting the value.
273 sub mk_group_ro_accessors {
274 my($self, $group, @fields) = @_;
276 $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields);
280 =head2 mk_group_wo_accessors
282 __PACKAGE__->mk_group_wo_accessors(simple => 'lie', [ subject => 'subj' ]);
286 =item Arguments: $group, @fieldspec
292 Creates a set of write only accessors in a given group. Identical to
293 L</mk_group_accessors> but accessors will throw an error if not passed a
294 value rather than getting the value.
298 sub mk_group_wo_accessors {
299 my($self, $group, @fields) = @_;
301 $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields);
309 =item Arguments: $field
315 Simple getter for hash-based objects which returns the value for the field
316 name passed as an argument.
328 =item Arguments: $field, $new_value
334 Simple setter for hash-based objects which sets and then returns the value
335 for the field name passed as an argument.
340 $_[0]->{$_[1]} = $_[2];
348 =item Arguments: $field
354 Simple getter for Classes and hash-based objects which returns the value for
355 the field name passed as an argument. This behaves much like
356 L<Class::Data::Accessor> where the field can be set in a base class,
357 inherited and changed in subclasses, and inherited and changed for object
363 if ( length (ref ($_[0]) ) ) {
364 if (Scalar::Util::reftype $_[0] eq 'HASH') {
365 return $_[0]->{$_[1]} if exists $_[0]->{$_[1]};
366 # everything in @_ is aliased, an assignment won't work
367 splice @_, 0, 1, ref($_[0]);
370 Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
374 # if we got this far there is nothing in the instance
375 # OR this is a class call
376 # in any case $_[0] contains the class name (see splice above)
378 no warnings 'uninitialized';
380 my $cag_slot = '::__cag_'. $_[1];
381 return ${$_[0].$cag_slot} if defined(${$_[0].$cag_slot});
383 do { return ${$_.$cag_slot} if defined(${$_.$cag_slot}) }
384 for $_[0]->get_super_paths;
393 =item Arguments: $field, $new_value
399 Simple setter for Classes and hash-based objects which sets and then returns
400 the value for the field name passed as an argument. When called on a hash-based
401 object it will set the appropriate hash key value. When called on a class, it
402 will set a class level variable.
404 B<Note:>: This method will die if you try to set an object variable on a non
410 if (length (ref ($_[0]) ) ) {
411 if (Scalar::Util::reftype $_[0] eq 'HASH') {
412 return $_[0]->{$_[1]} = $_[2];
414 Carp::croak('Cannot set inherited value on an object instance that is not hash-based');
419 ${$_[0].'::__cag_'.$_[1]} = $_[2];
422 =head2 get_component_class
426 =item Arguments: $field
432 Gets the value of the specified component class.
434 __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
436 $self->result_class->method();
439 $self->get_component_class('result_class')->method();
443 sub get_component_class {
444 $_[0]->get_inherited($_[1]);
447 =head2 set_component_class
451 =item Arguments: $field, $class
457 Inherited accessor that automatically loads the specified class before setting
458 it. This method will die if the specified class could not be loaded.
460 __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
461 __PACKAGE__->result_class('MyClass');
463 $self->result_class->method();
467 sub set_component_class {
468 if (defined $_[2] and length $_[2]) {
469 # disable warnings, and prevent $_ being eaten away by a behind-the-scenes
473 if (__CAG_ENV__::UNSTABLE_DOLLARAT) {
477 eval { Module::Runtime::use_package_optimistically($_[2]) }
480 Carp::croak("Could not load $_[1] '$_[2]': $err") if defined $err;
484 eval { Module::Runtime::use_package_optimistically($_[2]) }
485 or Carp::croak("Could not load $_[1] '$_[2]': $@");
489 $_[0]->set_inherited($_[1], $_[2]);
492 =head1 INTERNAL METHODS
494 These methods are documented for clarity, but are never meant to be called
495 directly, and are not really meant for overriding either.
497 =head2 get_super_paths
499 Returns a list of 'parent' or 'super' class names that the current class
500 inherited from. This is what drives the traversal done by L</get_inherited>.
504 sub get_super_paths {
505 # get_linear_isa returns the class itself as the 1st element
506 # use @_ as a pre-allocated scratch array
507 (undef, @_) = @{mro::get_linear_isa( length( ref($_[0]) ) ? ref($_[0]) : $_[0] )};
511 =head2 make_group_accessor
513 __PACKAGE__->make_group_accessor('simple', 'hair_length', 'hair_length');
514 __PACKAGE__->make_group_accessor('simple', 'hc', 'hair_color');
518 =item Arguments: $group, $field, $accessor
520 Returns: \&accessor_coderef ?
524 Called by mk_group_accessors for each entry in @fieldspec. Either returns
525 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
526 C<undef> if it elects to install the coderef on its own.
530 sub make_group_accessor { $gen_accessor->('rw', @_) }
532 =head2 make_group_ro_accessor
534 __PACKAGE__->make_group_ro_accessor('simple', 'birthdate', 'birthdate');
535 __PACKAGE__->make_group_ro_accessor('simple', 'ssn', 'social_security_number');
539 =item Arguments: $group, $field, $accessor
541 Returns: \&accessor_coderef ?
545 Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
546 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
547 C<undef> if it elects to install the coderef on its own.
551 sub make_group_ro_accessor { $gen_accessor->('ro', @_) }
553 =head2 make_group_wo_accessor
555 __PACKAGE__->make_group_wo_accessor('simple', 'lie', 'lie');
556 __PACKAGE__->make_group_wo_accessor('simple', 'subj', 'subject');
560 =item Arguments: $group, $field, $accessor
562 Returns: \&accessor_coderef ?
566 Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
567 a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
568 C<undef> if it elects to install the coderef on its own.
572 sub make_group_wo_accessor { $gen_accessor->('wo', @_) }
577 To provide total flexibility L<Class::Accessor::Grouped> calls methods
578 internally while performing get/set actions, which makes it noticeably
579 slower than similar modules. To compensate, this module will automatically
580 use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
581 accessors if this module is available on your system.
585 This is the benchmark of 200 get/get/set/get/set cycles on perl 5.16.2 with
586 thread support, showcasing how this modules L<simple (CAG_S)|/get_simple>,
587 L<inherited (CAG_INH)|/get_inherited> and L<inherited with parent-class data
588 (CAG_INHP)|/get_inherited> accessors stack up against most popular accessor
589 builders: L<Moose>, L<Moo>, L<Mo>, L<Mouse> (both pure-perl and XS variant),
590 L<Object::Tiny::RW (OTRW)|Object::Tiny::RW>,
591 L<Class::Accessor (CA)|Class::Accessor>,
592 L<Class::Accessor::Lite (CAL)|Class::Accessor::Lite>,
593 L<Class::Accessor::Fast (CAF)|Class::Accessor::Fast>,
594 L<Class::Accessor::Fast::XS (CAF_XS)|Class::Accessor::Fast::XS>
595 and L<Class::XSAccessor (XSA)|Class::XSAccessor>
597 Rate CAG_INHP CAG_INH CA CAG_S CAF moOse OTRW CAL mo moUse HANDMADE moo CAF_XS moUse_XS XSA
599 CAG_INHP 287.021+-0.02/s -- -0.3% -10.0% -37.1% -53.1% -53.6% -53.7% -54.1% -56.9% -59.0% -59.6% -59.8% -78.7% -81.9% -83.5%
601 CAG_INH 288.025+-0.031/s 0.3% -- -9.7% -36.9% -52.9% -53.5% -53.5% -53.9% -56.7% -58.8% -59.5% -59.7% -78.6% -81.9% -83.5%
603 CA 318.967+-0.047/s 11.1% 10.7% -- -30.1% -47.9% -48.5% -48.5% -49.0% -52.1% -54.4% -55.1% -55.3% -76.3% -79.9% -81.7%
605 CAG_S 456.107+-0.054/s 58.9% 58.4% 43.0% -- -25.4% -26.3% -26.4% -27.0% -31.5% -34.8% -35.8% -36.1% -66.1% -71.3% -73.9%
607 CAF 611.745+-0.099/s 113.1% 112.4% 91.8% 34.1% -- -1.2% -1.2% -2.1% -8.1% -12.6% -14.0% -14.3% -54.5% -61.5% -64.9%
609 moOse 619.051+-0.059/s 115.7% 114.9% 94.1% 35.7% 1.2% -- -0.1% -1.0% -7.0% -11.6% -12.9% -13.3% -54.0% -61.0% -64.5%
611 OTRW 619.475+-0.1/s 115.8% 115.1% 94.2% 35.8% 1.3% 0.1% -- -0.9% -6.9% -11.5% -12.9% -13.2% -54.0% -61.0% -64.5%
613 CAL 625.106+-0.085/s 117.8% 117.0% 96.0% 37.1% 2.2% 1.0% 0.9% -- -6.1% -10.7% -12.1% -12.5% -53.5% -60.6% -64.2%
615 mo 665.44+-0.12/s 131.8% 131.0% 108.6% 45.9% 8.8% 7.5% 7.4% 6.5% -- -4.9% -6.4% -6.8% -50.5% -58.1% -61.9%
617 moUse 699.9+-0.15/s 143.9% 143.0% 119.4% 53.5% 14.4% 13.1% 13.0% 12.0% 5.2% -- -1.6% -2.0% -48.0% -55.9% -59.9%
619 HANDMADE 710.98+-0.16/s 147.7% 146.8% 122.9% 55.9% 16.2% 14.9% 14.8% 13.7% 6.8% 1.6% -- -0.4% -47.2% -55.2% -59.2%
621 moo 714.04+-0.13/s 148.8% 147.9% 123.9% 56.6% 16.7% 15.3% 15.3% 14.2% 7.3% 2.0% 0.4% -- -46.9% -55.0% -59.1%
623 CAF_XS 1345.55+-0.051/s 368.8% 367.2% 321.8% 195.0% 120.0% 117.4% 117.2% 115.3% 102.2% 92.2% 89.3% 88.4% -- -15.3% -22.9%
625 moUse_XS 1588+-0.036/s 453.3% 451.3% 397.9% 248.2% 159.6% 156.5% 156.3% 154.0% 138.6% 126.9% 123.4% 122.4% 18.0% -- -9.0%
627 XSA 1744.67+-0.052/s 507.9% 505.7% 447.0% 282.5% 185.2% 181.8% 181.6% 179.1% 162.2% 149.3% 145.4% 144.3% 29.7% 9.9% --
629 Benchmarking program is available in the root of the
630 L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
632 =head2 Notes on Class::XSAccessor
634 You can force (or disable) the use of L<Class::XSAccessor> before creating a
635 particular C<simple> accessor by either manipulating the global variable
636 C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
637 L<localization|perlfunc/local>, or you can do so before runtime via the
638 C<CAG_USE_XS> environment variable.
640 Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
641 L</set_simple> this module does its best to detect if you are overriding
642 one of these methods and will fall back to using the perl version of the
643 accessor in order to maintain consistency. However be aware that if you
644 enable use of C<Class::XSAccessor> (automatically or explicitly), create
645 an object, invoke a simple accessor on that object, and B<then> manipulate
646 the symbol table to install a C<get/set_simple> override - you get to keep
651 Matt S. Trout <mst@shadowcatsystems.co.uk>
653 Christopher H. Laco <claco@chrislaco.com>
657 Caelum: Rafael Kitover <rkitover@cpan.org>
659 frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
661 groditi: Guillermo Roditi <groditi@cpan.org>
663 Jason Plum <jason.plum@bmmsi.com>
665 ribasushi: Peter Rabbitson <ribasushi@cpan.org>
668 =head1 COPYRIGHT & LICENSE
670 Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
672 This program is free software; you can redistribute it and/or modify
673 it under the same terms as perl itself.
677 ########################################################################
678 ########################################################################
679 ########################################################################
681 # Here be many angry dragons
682 # (all code is in private coderefs since everything inherits CAG)
684 ########################################################################
685 ########################################################################
687 # Autodetect unless flag supplied
688 my $xsa_autodetected;
689 if (! defined $USE_XS) {
690 $USE_XS = __CAG_ENV__::NO_CXSA ? 0 : 1;
695 my $maker_templates = {
697 cxsa_call => 'accessors',
698 pp_generator => sub {
699 # my ($group, $fieldname) = @_;
700 my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]);
701 sprintf <<'EOS', ($_[0], $quoted_fieldname) x 2;
704 ? shift->set_%s(%s, @_)
711 cxsa_call => 'getters',
712 pp_generator => sub {
713 # my ($group, $fieldname) = @_;
714 my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]);
715 sprintf <<'EOS', $_[0], $quoted_fieldname;
719 my ($meth) = (caller(0))[3] =~ /([^\:]+)$/;
720 my $class = length( ref($_[0]) ) ? ref($_[0]) : $_[0];
722 "'$meth' cannot alter its value (read-only attribute of class $class)"
731 cxsa_call => 'setters',
732 pp_generator => sub {
733 # my ($group, $fieldname) = @_;
734 my $quoted_fieldname = __CAG_ENV__::perlstring($_[1]);
735 sprintf <<'EOS', $_[0], $quoted_fieldname;
738 ? shift->set_%s(%s, @_)
740 my ($meth) = (caller(0))[3] =~ /([^\:]+)$/;
741 my $class = length( ref($_[0]) ) ? ref($_[0]) : $_[0];
743 "'$meth' cannot access its value (write-only attribute of class $class)"
753 #my ($src, $no_warnings, $err_msg) = @_;
755 my $src = sprintf "{ %s warnings; use strict; no strict 'refs'; %s }",
756 $_[1] ? 'no' : 'use',
762 local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
767 $err = $@ if $@ ne '';
770 Carp::croak(join ': ', ($_[2] || 'String-eval failed'), "$err\n$src\n" )
773 wantarray ? @rv : $rv[0];
776 my ($accessor_maker_cache, $no_xsa_warned_classes);
778 # can't use pkg_gen to track this stuff, as it doesn't
779 # detect superclass mucking
780 my $original_simple_getter = __PACKAGE__->can ('get_simple');
781 my $original_simple_setter = __PACKAGE__->can ('set_simple');
783 my ($resolved_methods, $cag_produced_crefs);
786 my @crefs = grep { defined $_ } values %{$cag_produced_crefs||{}};
787 $cag_produced_crefs = @crefs
788 ? { map { $_ => $_ } @crefs }
793 # Note!!! Unusual signature
794 $gen_accessor = sub {
795 my ($type, $class, $group, $field, $methname) = @_;
796 $class = ref $class if length ref $class;
798 # When installing an XSA simple accessor, we need to make sure we are not
799 # short-circuiting a (compile or runtime) get_simple/set_simple override.
800 # What we do here is install a lazy first-access check, which will decide
801 # the ultimate coderef being placed in the accessor slot
803 # Also note that the *original* class will always retain this shim, as
804 # different branches inheriting from it may have different overrides.
805 # Thus the final method (properly labeled and all) is installed in the
806 # calling-package's namespace
807 if ($USE_XS and $group eq 'simple') {
808 die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_ENV__::NO_CXSA )
809 if __CAG_ENV__::NO_CXSA;
812 my $current_class = length (ref ($_[0] ) ) ? ref ($_[0]) : $_[0];
814 my $resolved_implementation = $resolved_methods->{$current_class}{$methname} ||= do {
816 ($current_class->can('get_simple')||0) == $original_simple_getter
818 ($current_class->can('set_simple')||0) == $original_simple_setter
820 # nothing has changed, might as well use the XS crefs
822 # note that by the time this code executes, we already have
823 # *objects* (since XSA works on 'simple' only by definition).
824 # If someone is mucking with the symbol table *after* there
825 # are some objects already - look! many, shiny pieces! :)
827 # The weird breeder thingy is because XSA does not have an
828 # interface returning *just* a coderef, without installing it
830 Class::XSAccessor->import(
832 class => '__CAG__XSA__BREEDER__',
833 $maker_templates->{$type}{cxsa_call} => {
837 __CAG__XSA__BREEDER__->can($methname);
840 if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) {
841 # not using Carp since the line where this happens doesn't mean much
842 warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
843 . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or "
848 # that's faster than local
850 my $c = $gen_accessor->($type, $class, 'simple', $field, $methname);
857 # if after this shim was created someone wrapped it with an 'around',
858 # we can not blindly reinstall the method slot - we will destroy the
859 # wrapper. Silently chain execution further...
860 if ( ! $cag_produced_crefs->{ $current_class->can($methname) || 0 } ) {
862 # older perls segfault if the cref behind the goto throws
863 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
864 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
866 goto $resolved_implementation;
870 if (__CAG_ENV__::TRACK_UNDEFER_FAIL) {
871 my $deferred_calls_seen = do {
873 \%{"${current_class}::__cag_deferred_xs_shim_invocations"}
875 my @cframe = caller(0);
877 if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) {
879 "Deferred version of method $cframe[3] invoked more than once (originally "
880 . "invoked at $already_seen). This is a strong indication your code has "
881 . 'cached the original ->can derived method coderef, and is using it instead '
882 . 'of the proper method re-lookup, causing minor performance regressions'
886 $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]";
890 # install the resolved implementation into the code slot so we do not
891 # come here anymore (hopefully)
892 # since XSAccessor was available - so is Sub::Name
895 no warnings 'redefine';
897 my $fq_name = "${current_class}::${methname}";
898 *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation);
901 # now things are installed - one ref less to carry
902 delete $resolved_methods->{$current_class}{$methname};
904 # but need to record it in the expectation registry *in case* it
905 # was cached via ->can for some moronic reason
906 Scalar::Util::weaken( $cag_produced_crefs->{$resolved_implementation} = $resolved_implementation );
909 # older perls segfault if the cref behind the goto throws
910 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
911 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
913 goto $resolved_implementation;
916 Scalar::Util::weaken($cag_produced_crefs->{$ret} = $ret);
918 $ret; # returning shim
921 # no Sub::Name - just install the coderefs directly (compiling every time)
922 elsif (__CAG_ENV__::NO_SUBNAME) {
923 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
924 $maker_templates->{$type}{pp_generator}->($group, $field);
927 "no warnings 'redefine'; sub ${class}::${methname} { $src }; 1",
930 undef; # so that no further attempt will be made to install anything
933 # a coderef generator with a variable pad (returns a fresh cref on every invocation)
935 ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do {
936 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
937 $maker_templates->{$type}{pp_generator}->($group, $field);
939 $cag_eval->( "sub { my \$dummy; sub { \$dummy if 0; $src } }" );