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