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