Stop reexamining own class twice under 'inherited'
[p5sagit/Class-Accessor-Grouped.git] / lib / Class / Accessor / Grouped.pm
CommitLineData
963a69a5 1package Class::Accessor::Grouped;
2use strict;
3use warnings;
a0bce8bc 4use Carp ();
a0bce8bc 5use Scalar::Util ();
6d0e8ff2 6use Module::Runtime ();
df845078 7
8BEGIN {
6d0e8ff2 9 # use M::R to work around the 5.8 require bugs
df845078 10 if ($] < 5.009_005) {
6d0e8ff2 11 Module::Runtime::require_module('MRO::Compat');
df845078 12 }
13 else {
14 require mro;
15 }
16}
331e820d 17
ad0ed975 18our $VERSION = '0.10006';
d93670a5 19$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
963a69a5 20
80ebe3b6 21# when changing minimum version don't forget to adjust Makefile.PL as well
85ccab9a 22our $__minimum_xsa_version;
80ebe3b6 23BEGIN { $__minimum_xsa_version = '1.13' }
9f562456 24
8019c4d8 25our $USE_XS;
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}
ba8c183b 29 unless defined $USE_XS;
af169484 30
6d0e8ff2 31BEGIN {
32 package __CAG_ENV__;
33
34 die "Huh?! No minimum C::XSA version?!\n"
35 unless $__minimum_xsa_version;
36
37 local $@;
38 require constant;
39
40 # individual (one const at a time) imports so we are 5.6.2 compatible
41 # if we can - why not ;)
42 constant->import( NO_SUBNAME => eval {
43 Module::Runtime::require_module('Sub::Name')
44 } ? 0 : "$@" );
45
46 constant->import( NO_CXSA => ( !NO_SUBNAME() and eval {
47 Module::Runtime::use_module('Class::XSAccessor' => $__minimum_xsa_version)
48 } ) ? 0 : "$@" );
49
50 constant->import( BROKEN_GOTO => ($] < '5.008009') ? 1 : 0 );
51
52 constant->import( UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0 );
53
54 constant->import( TRACK_UNDEFER_FAIL => (
55 $INC{'Test/Builder.pm'} || $INC{'Test/Builder2.pm'}
56 and
57 $0 =~ m|^ x?t / .+ \.t $|x
58 ) ? 1 : 0 );
59}
60
8079caeb 61# Yes this method is undocumented
85ccab9a 62# Yes it should be a private coderef like all the rest at the end of this file
8079caeb 63# No we can't do that (yet) because the DBIC-CDBI compat layer overrides it
64# %$*@!?&!&#*$!!!
65sub _mk_group_accessors {
ba8c183b 66 my($self, $maker, $group, @fields) = @_;
67 my $class = Scalar::Util::blessed $self || $self;
eece2562 68
ba8c183b 69 no strict 'refs';
70 no warnings 'redefine';
eece2562 71
ba8c183b 72 # So we don't have to do lots of lookups inside the loop.
73 $maker = $self->can($maker) unless ref $maker;
eece2562 74
ba8c183b 75 for (@fields) {
eece2562 76
ba8c183b 77 my ($name, $field) = (ref $_) ? (@$_) : ($_, $_);
eece2562 78
33fe2299 79 for (qw/DESTROY AUTOLOAD CLONE/) {
80 Carp::carp("Having a data accessor named '$name' in '$class' is unwise.")
81 if $name eq $_;
82 }
83
ba8c183b 84 my $alias = "_${name}_accessor";
eece2562 85
ba8c183b 86 for my $meth ($name, $alias) {
eece2562 87
ba8c183b 88 # the maker may elect to not return anything, meaning it already
89 # installed the coderef for us (e.g. lack of Sub::Name)
90 my $cref = $self->$maker($group, $field, $meth)
91 or next;
eece2562 92
ba8c183b 93 my $fq_meth = "${class}::${meth}";
eece2562 94
ba8c183b 95 *$fq_meth = Sub::Name::subname($fq_meth, $cref);
96 #unless defined &{$class."\:\:$field"}
eece2562 97 }
ba8c183b 98 }
eece2562 99};
100
85ccab9a 101# coderef is setup at the end for clarity
102my $gen_accessor;
eece2562 103
963a69a5 104=head1 NAME
105
1ad8d8c6 106Class::Accessor::Grouped - Lets you build groups of accessors
963a69a5 107
108=head1 SYNOPSIS
109
3b118c10 110 use base 'Class::Accessor::Grouped';
111
112 # make basic accessors for objects
113 __PACKAGE__->mk_group_accessors(simple => qw(id name email));
114
115 # make accessor that works for objects and classes
116 __PACKAGE__->mk_group_accessors(inherited => 'awesome_level');
117
963a69a5 118=head1 DESCRIPTION
119
120This class lets you build groups of accessors that will call different
121getters and setters.
122
123=head1 METHODS
124
125=head2 mk_group_accessors
126
8e0a387b 127 __PACKAGE__->mk_group_accessors(simple => 'hair_length', [ hair_color => 'hc' ]);
18922520 128
963a69a5 129=over 4
130
131=item Arguments: $group, @fieldspec
132
133Returns: none
134
135=back
136
137Creates a set of accessors in a given group.
138
139$group is the name of the accessor group for the generated accessors; they
140will call get_$group($field) on get and set_$group($field, $value) on set.
141
22fa6720 142If you want to mimic Class::Accessor's mk_accessors $group has to be 'simple'
143to tell Class::Accessor::Grouped to use its own get_simple and set_simple
144methods.
145
963a69a5 146@fieldspec is a list of field/accessor names; if a fieldspec is a scalar
147this is used as both field and accessor name, if a listref it is expected to
148be of the form [ $accessor, $field ].
149
150=cut
151
152sub mk_group_accessors {
ba8c183b 153 my ($self, $group, @fields) = @_;
963a69a5 154
ba8c183b 155 $self->_mk_group_accessors('make_group_accessor', $group, @fields);
156 return;
963a69a5 157}
158
963a69a5 159=head2 mk_group_ro_accessors
160
8e0a387b 161 __PACKAGE__->mk_group_ro_accessors(simple => 'birthdate', [ social_security_number => 'ssn' ]);
18922520 162
963a69a5 163=over 4
164
165=item Arguments: $group, @fieldspec
166
167Returns: none
168
169=back
170
171Creates a set of read only accessors in a given group. Identical to
a557f8ad 172L</mk_group_accessors> but accessors will throw an error if passed a value
963a69a5 173rather than setting the value.
174
175=cut
176
177sub mk_group_ro_accessors {
ba8c183b 178 my($self, $group, @fields) = @_;
963a69a5 179
ba8c183b 180 $self->_mk_group_accessors('make_group_ro_accessor', $group, @fields);
963a69a5 181}
182
183=head2 mk_group_wo_accessors
184
8e0a387b 185 __PACKAGE__->mk_group_wo_accessors(simple => 'lie', [ subject => 'subj' ]);
18922520 186
963a69a5 187=over 4
188
189=item Arguments: $group, @fieldspec
190
191Returns: none
192
193=back
194
195Creates a set of write only accessors in a given group. Identical to
a557f8ad 196L</mk_group_accessors> but accessors will throw an error if not passed a
963a69a5 197value rather than getting the value.
198
199=cut
200
201sub mk_group_wo_accessors {
ba8c183b 202 my($self, $group, @fields) = @_;
963a69a5 203
ba8c183b 204 $self->_mk_group_accessors('make_group_wo_accessor', $group, @fields);
963a69a5 205}
206
963a69a5 207=head2 get_simple
208
209=over 4
210
211=item Arguments: $field
212
213Returns: $value
214
215=back
216
217Simple getter for hash-based objects which returns the value for the field
218name passed as an argument.
219
220=cut
221
222sub get_simple {
ba8c183b 223 return $_[0]->{$_[1]};
963a69a5 224}
225
226=head2 set_simple
227
228=over 4
229
230=item Arguments: $field, $new_value
231
232Returns: $new_value
233
234=back
235
236Simple setter for hash-based objects which sets and then returns the value
237for the field name passed as an argument.
238
239=cut
240
241sub set_simple {
ba8c183b 242 return $_[0]->{$_[1]} = $_[2];
963a69a5 243}
244
e6f2a0fd 245
246=head2 get_inherited
247
248=over 4
249
250=item Arguments: $field
251
252Returns: $value
253
254=back
255
331e820d 256Simple getter for Classes and hash-based objects which returns the value for
257the field name passed as an argument. This behaves much like
258L<Class::Data::Accessor> where the field can be set in a base class,
259inherited and changed in subclasses, and inherited and changed for object
260instances.
e6f2a0fd 261
262=cut
263
264sub get_inherited {
ba8c183b 265 my $class;
266
267 if ( defined( $class = Scalar::Util::blessed $_[0] ) ) {
268 if (Scalar::Util::reftype $_[0] eq 'HASH') {
269 return $_[0]->{$_[1]} if exists $_[0]->{$_[1]};
62cf9924 270 }
271 else {
ba8c183b 272 Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
62cf9924 273 }
ba8c183b 274 }
275 else {
276 $class = $_[0];
277 }
e6f2a0fd 278
ba8c183b 279 no strict 'refs';
280 no warnings 'uninitialized';
62cf9924 281
ba8c183b 282 my $cag_slot = '::__cag_'. $_[1];
283 return ${$class.$cag_slot} if defined(${$class.$cag_slot});
e6f2a0fd 284
a3a81175 285 do { return ${$_.$cag_slot} if defined(${$_.$cag_slot}) }
286 for $_[0]->get_super_paths;
c46050d3 287
ba8c183b 288 return undef;
e6f2a0fd 289}
290
291=head2 set_inherited
292
293=over 4
294
295=item Arguments: $field, $new_value
296
297Returns: $new_value
298
299=back
300
331e820d 301Simple setter for Classes and hash-based objects which sets and then returns
302the value for the field name passed as an argument. When called on a hash-based
303object it will set the appropriate hash key value. When called on a class, it
304will set a class level variable.
e6f2a0fd 305
331e820d 306B<Note:>: This method will die if you try to set an object variable on a non
307hash-based object.
e6f2a0fd 308
309=cut
310
311sub set_inherited {
ba8c183b 312 if (defined Scalar::Util::blessed $_[0]) {
313 if (Scalar::Util::reftype $_[0] eq 'HASH') {
314 return $_[0]->{$_[1]} = $_[2];
e6f2a0fd 315 } else {
ba8c183b 316 Carp::croak('Cannot set inherited value on an object instance that is not hash-based');
e6f2a0fd 317 };
ba8c183b 318 } else {
319 no strict 'refs';
320
321 return ${$_[0].'::__cag_'.$_[1]} = $_[2];
322 };
e6f2a0fd 323}
324
331e820d 325=head2 get_component_class
326
327=over 4
328
329=item Arguments: $field
330
331Returns: $value
332
333=back
334
335Gets the value of the specified component class.
336
ba8c183b 337 __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
97d76fb4 338
ba8c183b 339 $self->result_class->method();
97d76fb4 340
ba8c183b 341 ## same as
342 $self->get_component_class('result_class')->method();
331e820d 343
344=cut
345
346sub get_component_class {
ba8c183b 347 return $_[0]->get_inherited($_[1]);
331e820d 348};
349
350=head2 set_component_class
351
352=over 4
353
354=item Arguments: $field, $class
355
356Returns: $new_value
357
358=back
359
360Inherited accessor that automatically loads the specified class before setting
361it. This method will die if the specified class could not be loaded.
362
ba8c183b 363 __PACKAGE__->mk_group_accessors('component_class' => 'result_class');
364 __PACKAGE__->result_class('MyClass');
97d76fb4 365
ba8c183b 366 $self->result_class->method();
331e820d 367
368=cut
369
370sub set_component_class {
6d0e8ff2 371 if (defined $_[2] and length $_[2]) {
372 # disable warnings, and prevent $_ being eaten away by a behind-the-scenes
373 # module loading
374 local ($^W, $_);
375
376 if (__CAG_ENV__::UNSTABLE_DOLLARAT) {
377 my $err;
378 {
379 local $@;
380 eval { Module::Runtime::use_package_optimistically($_[2]) }
381 or $err = $@;
382 }
383 Carp::croak("Could not load $_[1] '$_[2]': $err") if defined $err;
ba8c183b 384
6d0e8ff2 385 }
386 else {
387 eval { Module::Runtime::use_package_optimistically($_[2]) }
388 or Carp::croak("Could not load $_[1] '$_[2]': $@");
389 }
ba8c183b 390 };
331e820d 391
ba8c183b 392 return $_[0]->set_inherited($_[1], $_[2]);
331e820d 393};
394
8e0a387b 395=head1 INTERNAL METHODS
396
397These methods are documented for clarity, but are never meant to be called
398directly, and are not really meant for overriding either.
399
a49c32d9 400=head2 get_super_paths
401
8e0a387b 402Returns a list of 'parent' or 'super' class names that the current class
403inherited from. This is what drives the traversal done by L</get_inherited>.
a49c32d9 404
405=cut
406
407sub get_super_paths {
cc8ab1f2 408 # get_linear_isa returns the class itself as the 1st element
409 # use @_ as a pre-allocated scratch array
410 (undef, @_) = @{mro::get_linear_isa( length( ref($_[0]) ) ? ref($_[0]) : $_[0] )};
411 @_;
a49c32d9 412};
413
8e0a387b 414=head2 make_group_accessor
415
416 __PACKAGE__->make_group_accessor('simple', 'hair_length', 'hair_length');
417 __PACKAGE__->make_group_accessor('simple', 'hc', 'hair_color');
418
419=over 4
420
421=item Arguments: $group, $field, $accessor
422
423Returns: \&accessor_coderef ?
424
425=back
426
427Called by mk_group_accessors for each entry in @fieldspec. Either returns
428a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
429C<undef> if it elects to install the coderef on its own.
430
431=cut
432
433sub make_group_accessor { $gen_accessor->('rw', @_) }
434
435=head2 make_group_ro_accessor
436
437 __PACKAGE__->make_group_ro_accessor('simple', 'birthdate', 'birthdate');
438 __PACKAGE__->make_group_ro_accessor('simple', 'ssn', 'social_security_number');
439
440=over 4
441
442=item Arguments: $group, $field, $accessor
443
444Returns: \&accessor_coderef ?
445
446=back
447
448Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
449a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
450C<undef> if it elects to install the coderef on its own.
451
452=cut
453
454sub make_group_ro_accessor { $gen_accessor->('ro', @_) }
455
456=head2 make_group_wo_accessor
457
458 __PACKAGE__->make_group_wo_accessor('simple', 'lie', 'lie');
459 __PACKAGE__->make_group_wo_accessor('simple', 'subj', 'subject');
460
461=over 4
462
463=item Arguments: $group, $field, $accessor
464
465Returns: \&accessor_coderef ?
466
467=back
468
469Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
470a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
471C<undef> if it elects to install the coderef on its own.
472
473=cut
474
475sub make_group_wo_accessor { $gen_accessor->('wo', @_) }
476
477
9d7d52da 478=head1 PERFORMANCE
15cf8e32 479
8019c4d8 480To provide total flexibility L<Class::Accessor::Grouped> calls methods
481internally while performing get/set actions, which makes it noticeably
482slower than similar modules. To compensate, this module will automatically
483use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
b36cd259 484accessors if this module is available on your system.
8019c4d8 485
486=head2 Benchmark
487
488This is the result of a set/get/set loop benchmark on perl 5.12.1 with
489thread support, showcasing most popular accessor builders: L<Moose>, L<Mouse>,
af71d687 490L<Moo>, L<CAF|Class::Accessor::Fast>, L<CAF_XS|Class::Accessor::Fast::XS>,
491L<XSA|Class::XSAccessor>, and L<CAF_XSA|Class::XSAccessor::Compat>:
492
493 Rate CAG moOse CAF moUse moo HANDMADE CAF_XS moUse_XS moo_XS CAF_XSA XSA CAG_XS
494 CAG 169/s -- -21% -24% -32% -32% -34% -59% -63% -67% -67% -67% -67%
495 moOse 215/s 27% -- -3% -13% -13% -15% -48% -53% -58% -58% -58% -58%
496 CAF 222/s 31% 3% -- -10% -10% -13% -46% -52% -57% -57% -57% -57%
497 moUse 248/s 46% 15% 11% -- -0% -3% -40% -46% -52% -52% -52% -52%
498 moo 248/s 46% 15% 11% 0% -- -3% -40% -46% -52% -52% -52% -52%
499 HANDMADE 255/s 50% 18% 14% 3% 3% -- -38% -45% -50% -51% -51% -51%
500 CAF_XS 411/s 143% 91% 85% 66% 66% 61% -- -11% -20% -20% -21% -21%
501 moUse_XS 461/s 172% 114% 107% 86% 86% 81% 12% -- -10% -11% -11% -11%
502 moo_XS 514/s 204% 139% 131% 107% 107% 102% 25% 12% -- -0% -1% -1%
503 CAF_XSA 516/s 205% 140% 132% 108% 108% 103% 26% 12% 0% -- -0% -0%
504 XSA 519/s 206% 141% 133% 109% 109% 104% 26% 13% 1% 0% -- -0%
505 CAG_XS 519/s 206% 141% 133% 109% 109% 104% 26% 13% 1% 0% 0% --
8019c4d8 506
507Benchmark program is available in the root of the
508L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
509
510=head2 Notes on Class::XSAccessor
511
bd83e674 512You can force (or disable) the use of L<Class::XSAccessor> before creating a
513particular C<simple> accessor by either manipulating the global variable
514C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
515L<localization|perlfunc/local>, or you can do so before runtime via the
516C<CAG_USE_XS> environment variable.
517
518Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
519L</set_simple> this module does its best to detect if you are overriding
520one of these methods and will fall back to using the perl version of the
521accessor in order to maintain consistency. However be aware that if you
522enable use of C<Class::XSAccessor> (automatically or explicitly), create
523an object, invoke a simple accessor on that object, and B<then> manipulate
524the symbol table to install a C<get/set_simple> override - you get to keep
525all the pieces.
526
963a69a5 527=head1 AUTHORS
528
529Matt S. Trout <mst@shadowcatsystems.co.uk>
ba6f7b1b 530
97972dcb 531Christopher H. Laco <claco@chrislaco.com>
963a69a5 532
8ef9b3ff 533=head1 CONTRIBUTORS
dfb86526 534
ba6f7b1b 535Caelum: Rafael Kitover <rkitover@cpan.org>
536
3b118c10 537frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
538
8ef9b3ff 539groditi: Guillermo Roditi <groditi@cpan.org>
ba6f7b1b 540
6a4c729f 541Jason Plum <jason.plum@bmmsi.com>
dfb86526 542
ba6f7b1b 543ribasushi: Peter Rabbitson <ribasushi@cpan.org>
544
545
4fe25633 546=head1 COPYRIGHT & LICENSE
963a69a5 547
af169484 548Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
963a69a5 549
4fe25633 550This program is free software; you can redistribute it and/or modify
551it under the same terms as perl itself.
963a69a5 552
4fe25633 553=cut
85ccab9a 554
555########################################################################
556########################################################################
557########################################################################
558#
559# Here be many angry dragons
560# (all code is in private coderefs since everything inherits CAG)
561#
562########################################################################
563########################################################################
564
85ccab9a 565# Autodetect unless flag supplied
85ccab9a 566my $xsa_autodetected;
567if (! defined $USE_XS) {
3f6054c4 568 $USE_XS = __CAG_ENV__::NO_CXSA ? 0 : 1;
85ccab9a 569 $xsa_autodetected++;
570}
571
572my $maker_templates = {
573 rw => {
574 xs_call => 'accessors',
575 pp_code => sub {
98694bf0 576 my $set = "set_$_[0]";
577 my $get = "get_$_[0]";
578 my $field = $_[1];
85ccab9a 579 $field =~ s/'/\\'/g;
580
581 "
af71d687 582 \@_ != 1
85ccab9a 583 ? shift->$set('$field', \@_)
584 : shift->$get('$field')
585 "
586 },
587 },
588 ro => {
589 xs_call => 'getters',
590 pp_code => sub {
98694bf0 591 my $get = "get_$_[0]";
592 my $field = $_[1];
85ccab9a 593 $field =~ s/'/\\'/g;
594
595 "
596 \@_ == 1
597 ? shift->$get('$field')
598 : do {
599 my \$caller = caller;
98694bf0 600 my \$class = ref \$_[0] || \$_[0];
601 Carp::croak(\"'\$caller' cannot alter the value of '$field' \".
602 \"(read-only attributes of class '\$class')\");
85ccab9a 603 }
604 "
605 },
606 },
607 wo => {
608 xs_call => 'setters',
609 pp_code => sub {
98694bf0 610 my $set = "set_$_[0]";
611 my $field = $_[1];
85ccab9a 612 $field =~ s/'/\\'/g;
613
614 "
af71d687 615 \@_ != 1
85ccab9a 616 ? shift->$set('$field', \@_)
617 : do {
618 my \$caller = caller;
98694bf0 619 my \$class = ref \$_[0] || \$_[0];
620 Carp::croak(\"'\$caller' cannot access the value of '$field' \".
621 \"(write-only attributes of class '\$class')\");
85ccab9a 622 }
623 "
624 },
625 },
626};
627
628
629my ($accessor_maker_cache, $no_xsa_warned_classes);
630
631# can't use pkg_gen to track this stuff, as it doesn't
632# detect superclass mucking
633my $original_simple_getter = __PACKAGE__->can ('get_simple');
634my $original_simple_setter = __PACKAGE__->can ('set_simple');
635
636# Note!!! Unusual signature
637$gen_accessor = sub {
638 my ($type, $class, $group, $field, $methname) = @_;
34051fe0 639 if (my $c = Scalar::Util::blessed( $class )) {
85ccab9a 640 $class = $c;
641 }
642
643 # When installing an XSA simple accessor, we need to make sure we are not
644 # short-circuiting a (compile or runtime) get_simple/set_simple override.
645 # What we do here is install a lazy first-access check, which will decide
646 # the ultimate coderef being placed in the accessor slot
f7cf6867 647 #
648 # Also note that the *original* class will always retain this shim, as
649 # different branches inheriting from it may have different overrides.
650 # Thus the final method (properly labeled and all) is installed in the
651 # calling-package's namespace
85ccab9a 652 if ($USE_XS and $group eq 'simple') {
3f6054c4 653 die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_ENV__::NO_CXSA )
654 if __CAG_ENV__::NO_CXSA;
f7cf6867 655
de167379 656 my ($expected_cref, $cached_implementation);
657 my $ret = $expected_cref = sub {
f7cf6867 658 my $current_class = Scalar::Util::blessed( $_[0] ) || $_[0];
659
de167379 660 # $cached_implementation will be set only if the shim got
661 # 'around'ed, in which case it is handy to avoid re-running
662 # this block over and over again
663 my $resolved_implementation = $cached_implementation->{$current_class} || do {
664 if (
ad0ed975 665 ($current_class->can('get_simple')||0) == $original_simple_getter
de167379 666 &&
ad0ed975 667 ($current_class->can('set_simple')||0) == $original_simple_setter
de167379 668 ) {
669 # nothing has changed, might as well use the XS crefs
670 #
671 # note that by the time this code executes, we already have
672 # *objects* (since XSA works on 'simple' only by definition).
673 # If someone is mucking with the symbol table *after* there
674 # are some objects already - look! many, shiny pieces! :)
675 #
676 # The weird breeder thingy is because XSA does not have an
677 # interface returning *just* a coderef, without installing it
678 # anywhere :(
679 Class::XSAccessor->import(
680 replace => 1,
681 class => '__CAG__XSA__BREEDER__',
682 $maker_templates->{$type}{xs_call} => {
683 $methname => $field,
684 },
685 );
686 __CAG__XSA__BREEDER__->can($methname);
687 }
688 else {
689 if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) {
690 # not using Carp since the line where this happens doesn't mean much
691 warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
692 . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or "
693 . "set_simple\n";
694 }
695
696 do {
697 # that's faster than local
698 $USE_XS = 0;
699 my $c = $gen_accessor->($type, $class, 'simple', $field, $methname);
700 $USE_XS = 1;
701 $c;
702 };
703 }
704 };
705
706 # if after this shim was created someone wrapped it with an 'around',
707 # we can not blindly reinstall the method slot - we will destroy the
708 # wrapper. Silently chain execution further...
ad0ed975 709 if ( !$expected_cref or $expected_cref != ($current_class->can($methname)||0) ) {
de167379 710
711 # there is no point in re-determining it on every subsequent call,
712 # just store for future reference
713 $cached_implementation->{$current_class} ||= $resolved_implementation;
714
715 # older perls segfault if the cref behind the goto throws
716 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
3f6054c4 717 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
de167379 718
719 goto $resolved_implementation;
720 }
721
3f6054c4 722 if (__CAG_ENV__::TRACK_UNDEFER_FAIL) {
2d392af1 723 my $deferred_calls_seen = do {
724 no strict 'refs';
725 \%{"${current_class}::__cag_deferred_xs_shim_invocations"}
726 };
e6f2993f 727 my @cframe = caller(0);
2d392af1 728 if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) {
e6f2993f 729 Carp::carp (
730 "Deferred version of method $cframe[3] invoked more than once (originally "
2d392af1 731 . "invoked at $already_seen). This is a strong indication your code has "
732 . 'cached the original ->can derived method coderef, and is using it instead '
733 . 'of the proper method re-lookup, causing performance regressions'
e6f2993f 734 );
735 }
736 else {
2d392af1 737 $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]";
e6f2993f 738 }
739 }
740
de167379 741 # install the resolved implementation into the code slot so we do not
742 # come here anymore (hopefully)
743 # since XSAccessor was available - so is Sub::Name
744 {
e6f2993f 745 no strict 'refs';
746 no warnings 'redefine';
85ccab9a 747
f7cf6867 748 my $fq_name = "${current_class}::${methname}";
de167379 749 *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation);
750
751 # need to update what the shim expects too *in case* its
752 # ->can was cached for some moronic reason
753 $expected_cref = $resolved_implementation;
754 Scalar::Util::weaken($expected_cref);
f7cf6867 755 }
85ccab9a 756
f7cf6867 757 # older perls segfault if the cref behind the goto throws
758 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
3f6054c4 759 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
85ccab9a 760
de167379 761 goto $resolved_implementation;
f7cf6867 762 };
de167379 763
764 Scalar::Util::weaken($expected_cref); # to break the self-reference
765 $ret;
85ccab9a 766 }
767
768 # no Sub::Name - just install the coderefs directly (compiling every time)
3f6054c4 769 elsif (__CAG_ENV__::NO_SUBNAME) {
eda06cc6 770 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
771 $maker_templates->{$type}{pp_code}->($group, $field);
772
fdb75175 773 no warnings 'redefine';
3f6054c4 774 local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
bd975094 775 eval "sub ${class}::${methname} { $src }";
eda06cc6 776
e6f2993f 777 undef; # so that no further attempt will be made to install anything
85ccab9a 778 }
779
780 # a coderef generator with a variable pad (returns a fresh cref on every invocation)
85ccab9a 781 else {
e6f2993f 782 ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do {
eda06cc6 783 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
784 $maker_templates->{$type}{pp_code}->($group, $field);
785
3f6054c4 786 local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
eda06cc6 787 eval "sub { my \$dummy; sub { \$dummy if 0; $src } }" or die $@;
85ccab9a 788 })->()
789 }
790};
791
7921;