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