The complexity of caching pkg_gen is in fact making things slower
[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 {
ba8c183b 408 return @{mro::get_linear_isa( ref($_[0]) || $_[0] )};
a49c32d9 409};
410
8e0a387b 411=head2 make_group_accessor
412
413 __PACKAGE__->make_group_accessor('simple', 'hair_length', 'hair_length');
414 __PACKAGE__->make_group_accessor('simple', 'hc', 'hair_color');
415
416=over 4
417
418=item Arguments: $group, $field, $accessor
419
420Returns: \&accessor_coderef ?
421
422=back
423
424Called by mk_group_accessors for each entry in @fieldspec. Either returns
425a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
426C<undef> if it elects to install the coderef on its own.
427
428=cut
429
430sub make_group_accessor { $gen_accessor->('rw', @_) }
431
432=head2 make_group_ro_accessor
433
434 __PACKAGE__->make_group_ro_accessor('simple', 'birthdate', 'birthdate');
435 __PACKAGE__->make_group_ro_accessor('simple', 'ssn', 'social_security_number');
436
437=over 4
438
439=item Arguments: $group, $field, $accessor
440
441Returns: \&accessor_coderef ?
442
443=back
444
445Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
446a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
447C<undef> if it elects to install the coderef on its own.
448
449=cut
450
451sub make_group_ro_accessor { $gen_accessor->('ro', @_) }
452
453=head2 make_group_wo_accessor
454
455 __PACKAGE__->make_group_wo_accessor('simple', 'lie', 'lie');
456 __PACKAGE__->make_group_wo_accessor('simple', 'subj', 'subject');
457
458=over 4
459
460=item Arguments: $group, $field, $accessor
461
462Returns: \&accessor_coderef ?
463
464=back
465
466Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
467a coderef which will be installed at C<&__PACKAGE__::$accessor>, or returns
468C<undef> if it elects to install the coderef on its own.
469
470=cut
471
472sub make_group_wo_accessor { $gen_accessor->('wo', @_) }
473
474
9d7d52da 475=head1 PERFORMANCE
15cf8e32 476
8019c4d8 477To provide total flexibility L<Class::Accessor::Grouped> calls methods
478internally while performing get/set actions, which makes it noticeably
479slower than similar modules. To compensate, this module will automatically
480use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
b36cd259 481accessors if this module is available on your system.
8019c4d8 482
483=head2 Benchmark
484
485This is the result of a set/get/set loop benchmark on perl 5.12.1 with
486thread support, showcasing most popular accessor builders: L<Moose>, L<Mouse>,
af71d687 487L<Moo>, L<CAF|Class::Accessor::Fast>, L<CAF_XS|Class::Accessor::Fast::XS>,
488L<XSA|Class::XSAccessor>, and L<CAF_XSA|Class::XSAccessor::Compat>:
489
490 Rate CAG moOse CAF moUse moo HANDMADE CAF_XS moUse_XS moo_XS CAF_XSA XSA CAG_XS
491 CAG 169/s -- -21% -24% -32% -32% -34% -59% -63% -67% -67% -67% -67%
492 moOse 215/s 27% -- -3% -13% -13% -15% -48% -53% -58% -58% -58% -58%
493 CAF 222/s 31% 3% -- -10% -10% -13% -46% -52% -57% -57% -57% -57%
494 moUse 248/s 46% 15% 11% -- -0% -3% -40% -46% -52% -52% -52% -52%
495 moo 248/s 46% 15% 11% 0% -- -3% -40% -46% -52% -52% -52% -52%
496 HANDMADE 255/s 50% 18% 14% 3% 3% -- -38% -45% -50% -51% -51% -51%
497 CAF_XS 411/s 143% 91% 85% 66% 66% 61% -- -11% -20% -20% -21% -21%
498 moUse_XS 461/s 172% 114% 107% 86% 86% 81% 12% -- -10% -11% -11% -11%
499 moo_XS 514/s 204% 139% 131% 107% 107% 102% 25% 12% -- -0% -1% -1%
500 CAF_XSA 516/s 205% 140% 132% 108% 108% 103% 26% 12% 0% -- -0% -0%
501 XSA 519/s 206% 141% 133% 109% 109% 104% 26% 13% 1% 0% -- -0%
502 CAG_XS 519/s 206% 141% 133% 109% 109% 104% 26% 13% 1% 0% 0% --
8019c4d8 503
504Benchmark program is available in the root of the
505L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
506
507=head2 Notes on Class::XSAccessor
508
bd83e674 509You can force (or disable) the use of L<Class::XSAccessor> before creating a
510particular C<simple> accessor by either manipulating the global variable
511C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
512L<localization|perlfunc/local>, or you can do so before runtime via the
513C<CAG_USE_XS> environment variable.
514
515Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
516L</set_simple> this module does its best to detect if you are overriding
517one of these methods and will fall back to using the perl version of the
518accessor in order to maintain consistency. However be aware that if you
519enable use of C<Class::XSAccessor> (automatically or explicitly), create
520an object, invoke a simple accessor on that object, and B<then> manipulate
521the symbol table to install a C<get/set_simple> override - you get to keep
522all the pieces.
523
963a69a5 524=head1 AUTHORS
525
526Matt S. Trout <mst@shadowcatsystems.co.uk>
ba6f7b1b 527
97972dcb 528Christopher H. Laco <claco@chrislaco.com>
963a69a5 529
8ef9b3ff 530=head1 CONTRIBUTORS
dfb86526 531
ba6f7b1b 532Caelum: Rafael Kitover <rkitover@cpan.org>
533
3b118c10 534frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
535
8ef9b3ff 536groditi: Guillermo Roditi <groditi@cpan.org>
ba6f7b1b 537
6a4c729f 538Jason Plum <jason.plum@bmmsi.com>
dfb86526 539
ba6f7b1b 540ribasushi: Peter Rabbitson <ribasushi@cpan.org>
541
542
4fe25633 543=head1 COPYRIGHT & LICENSE
963a69a5 544
af169484 545Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
963a69a5 546
4fe25633 547This program is free software; you can redistribute it and/or modify
548it under the same terms as perl itself.
963a69a5 549
4fe25633 550=cut
85ccab9a 551
552########################################################################
553########################################################################
554########################################################################
555#
556# Here be many angry dragons
557# (all code is in private coderefs since everything inherits CAG)
558#
559########################################################################
560########################################################################
561
85ccab9a 562# Autodetect unless flag supplied
85ccab9a 563my $xsa_autodetected;
564if (! defined $USE_XS) {
3f6054c4 565 $USE_XS = __CAG_ENV__::NO_CXSA ? 0 : 1;
85ccab9a 566 $xsa_autodetected++;
567}
568
569my $maker_templates = {
570 rw => {
571 xs_call => 'accessors',
572 pp_code => sub {
98694bf0 573 my $set = "set_$_[0]";
574 my $get = "get_$_[0]";
575 my $field = $_[1];
85ccab9a 576 $field =~ s/'/\\'/g;
577
578 "
af71d687 579 \@_ != 1
85ccab9a 580 ? shift->$set('$field', \@_)
581 : shift->$get('$field')
582 "
583 },
584 },
585 ro => {
586 xs_call => 'getters',
587 pp_code => sub {
98694bf0 588 my $get = "get_$_[0]";
589 my $field = $_[1];
85ccab9a 590 $field =~ s/'/\\'/g;
591
592 "
593 \@_ == 1
594 ? shift->$get('$field')
595 : do {
596 my \$caller = caller;
98694bf0 597 my \$class = ref \$_[0] || \$_[0];
598 Carp::croak(\"'\$caller' cannot alter the value of '$field' \".
599 \"(read-only attributes of class '\$class')\");
85ccab9a 600 }
601 "
602 },
603 },
604 wo => {
605 xs_call => 'setters',
606 pp_code => sub {
98694bf0 607 my $set = "set_$_[0]";
608 my $field = $_[1];
85ccab9a 609 $field =~ s/'/\\'/g;
610
611 "
af71d687 612 \@_ != 1
85ccab9a 613 ? shift->$set('$field', \@_)
614 : do {
615 my \$caller = caller;
98694bf0 616 my \$class = ref \$_[0] || \$_[0];
617 Carp::croak(\"'\$caller' cannot access the value of '$field' \".
618 \"(write-only attributes of class '\$class')\");
85ccab9a 619 }
620 "
621 },
622 },
623};
624
625
626my ($accessor_maker_cache, $no_xsa_warned_classes);
627
628# can't use pkg_gen to track this stuff, as it doesn't
629# detect superclass mucking
630my $original_simple_getter = __PACKAGE__->can ('get_simple');
631my $original_simple_setter = __PACKAGE__->can ('set_simple');
632
633# Note!!! Unusual signature
634$gen_accessor = sub {
635 my ($type, $class, $group, $field, $methname) = @_;
34051fe0 636 if (my $c = Scalar::Util::blessed( $class )) {
85ccab9a 637 $class = $c;
638 }
639
640 # When installing an XSA simple accessor, we need to make sure we are not
641 # short-circuiting a (compile or runtime) get_simple/set_simple override.
642 # What we do here is install a lazy first-access check, which will decide
643 # the ultimate coderef being placed in the accessor slot
f7cf6867 644 #
645 # Also note that the *original* class will always retain this shim, as
646 # different branches inheriting from it may have different overrides.
647 # Thus the final method (properly labeled and all) is installed in the
648 # calling-package's namespace
85ccab9a 649 if ($USE_XS and $group eq 'simple') {
3f6054c4 650 die sprintf( "Class::XSAccessor requested but not available:\n%s\n", __CAG_ENV__::NO_CXSA )
651 if __CAG_ENV__::NO_CXSA;
f7cf6867 652
de167379 653 my ($expected_cref, $cached_implementation);
654 my $ret = $expected_cref = sub {
f7cf6867 655 my $current_class = Scalar::Util::blessed( $_[0] ) || $_[0];
656
de167379 657 # $cached_implementation will be set only if the shim got
658 # 'around'ed, in which case it is handy to avoid re-running
659 # this block over and over again
660 my $resolved_implementation = $cached_implementation->{$current_class} || do {
661 if (
ad0ed975 662 ($current_class->can('get_simple')||0) == $original_simple_getter
de167379 663 &&
ad0ed975 664 ($current_class->can('set_simple')||0) == $original_simple_setter
de167379 665 ) {
666 # nothing has changed, might as well use the XS crefs
667 #
668 # note that by the time this code executes, we already have
669 # *objects* (since XSA works on 'simple' only by definition).
670 # If someone is mucking with the symbol table *after* there
671 # are some objects already - look! many, shiny pieces! :)
672 #
673 # The weird breeder thingy is because XSA does not have an
674 # interface returning *just* a coderef, without installing it
675 # anywhere :(
676 Class::XSAccessor->import(
677 replace => 1,
678 class => '__CAG__XSA__BREEDER__',
679 $maker_templates->{$type}{xs_call} => {
680 $methname => $field,
681 },
682 );
683 __CAG__XSA__BREEDER__->can($methname);
684 }
685 else {
686 if (! $xsa_autodetected and ! $no_xsa_warned_classes->{$current_class}++) {
687 # not using Carp since the line where this happens doesn't mean much
688 warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
689 . "'$current_class' inheriting from '$class' due to an overriden get_simple and/or "
690 . "set_simple\n";
691 }
692
693 do {
694 # that's faster than local
695 $USE_XS = 0;
696 my $c = $gen_accessor->($type, $class, 'simple', $field, $methname);
697 $USE_XS = 1;
698 $c;
699 };
700 }
701 };
702
703 # if after this shim was created someone wrapped it with an 'around',
704 # we can not blindly reinstall the method slot - we will destroy the
705 # wrapper. Silently chain execution further...
ad0ed975 706 if ( !$expected_cref or $expected_cref != ($current_class->can($methname)||0) ) {
de167379 707
708 # there is no point in re-determining it on every subsequent call,
709 # just store for future reference
710 $cached_implementation->{$current_class} ||= $resolved_implementation;
711
712 # older perls segfault if the cref behind the goto throws
713 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
3f6054c4 714 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
de167379 715
716 goto $resolved_implementation;
717 }
718
3f6054c4 719 if (__CAG_ENV__::TRACK_UNDEFER_FAIL) {
2d392af1 720 my $deferred_calls_seen = do {
721 no strict 'refs';
722 \%{"${current_class}::__cag_deferred_xs_shim_invocations"}
723 };
e6f2993f 724 my @cframe = caller(0);
2d392af1 725 if (my $already_seen = $deferred_calls_seen->{$cframe[3]}) {
e6f2993f 726 Carp::carp (
727 "Deferred version of method $cframe[3] invoked more than once (originally "
2d392af1 728 . "invoked at $already_seen). This is a strong indication your code has "
729 . 'cached the original ->can derived method coderef, and is using it instead '
730 . 'of the proper method re-lookup, causing performance regressions'
e6f2993f 731 );
732 }
733 else {
2d392af1 734 $deferred_calls_seen->{$cframe[3]} = "$cframe[1] line $cframe[2]";
e6f2993f 735 }
736 }
737
de167379 738 # install the resolved implementation into the code slot so we do not
739 # come here anymore (hopefully)
740 # since XSAccessor was available - so is Sub::Name
741 {
e6f2993f 742 no strict 'refs';
743 no warnings 'redefine';
85ccab9a 744
f7cf6867 745 my $fq_name = "${current_class}::${methname}";
de167379 746 *$fq_name = Sub::Name::subname($fq_name, $resolved_implementation);
747
748 # need to update what the shim expects too *in case* its
749 # ->can was cached for some moronic reason
750 $expected_cref = $resolved_implementation;
751 Scalar::Util::weaken($expected_cref);
f7cf6867 752 }
85ccab9a 753
f7cf6867 754 # older perls segfault if the cref behind the goto throws
755 # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
3f6054c4 756 return $resolved_implementation->(@_) if __CAG_ENV__::BROKEN_GOTO;
85ccab9a 757
de167379 758 goto $resolved_implementation;
f7cf6867 759 };
de167379 760
761 Scalar::Util::weaken($expected_cref); # to break the self-reference
762 $ret;
85ccab9a 763 }
764
765 # no Sub::Name - just install the coderefs directly (compiling every time)
3f6054c4 766 elsif (__CAG_ENV__::NO_SUBNAME) {
eda06cc6 767 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
768 $maker_templates->{$type}{pp_code}->($group, $field);
769
fdb75175 770 no warnings 'redefine';
3f6054c4 771 local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
bd975094 772 eval "sub ${class}::${methname} { $src }";
eda06cc6 773
e6f2993f 774 undef; # so that no further attempt will be made to install anything
85ccab9a 775 }
776
777 # a coderef generator with a variable pad (returns a fresh cref on every invocation)
85ccab9a 778 else {
e6f2993f 779 ($accessor_maker_cache->{pp}{$type}{$group}{$field} ||= do {
eda06cc6 780 my $src = $accessor_maker_cache->{source}{$type}{$group}{$field} ||=
781 $maker_templates->{$type}{pp_code}->($group, $field);
782
3f6054c4 783 local $@ if __CAG_ENV__::UNSTABLE_DOLLARAT;
eda06cc6 784 eval "sub { my \$dummy; sub { \$dummy if 0; $src } }" or die $@;
85ccab9a 785 })->()
786 }
787};
788
7891;