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