File Coverage

blib/lib/MooseX/XSAccessor.pm
Criterion Covered Total %
statement 35 35 100.0
branch 4 4 100.0
condition 2 3 66.6
subroutine 11 11 100.0
pod 2 2 100.0
total 54 55 98.1


line stmt bran cond sub pod time code
1             package MooseX::XSAccessor;
2              
3 44     44   24008957 use 5.008;
  44         570  
4 44     44   350 use strict;
  44         98  
  44         1164  
5 44     44   247 use warnings;
  44         97  
  44         1630  
6              
7 44     44   283 use Moose 2.0600 ();
  44         890  
  44         1046  
8 44     44   18439 use MooseX::XSAccessor::Trait::Attribute ();
  44         123  
  44         1277  
9 44     44   309 use Scalar::Util qw(blessed);
  44         104  
  44         2663  
10              
11             BEGIN {
12 44     44   161 $MooseX::XSAccessor::AUTHORITY = 'cpan:TOBYINK';
13 44         1095 $MooseX::XSAccessor::VERSION = '0.010';
14             }
15              
16             our $LVALUE;
17              
18 44     44   701 use Moose::Exporter;
  44         86  
  44         234  
19             "Moose::Exporter"->setup_import_methods;
20              
21             sub init_meta {
22 139     139 1 1468881 shift;
23 139         1016 my %p = @_;
24             Moose::Util::MetaRole::apply_metaroles(
25             for => $p{for_class},
26 139         1088 class_metaroles => {
27             attribute => [qw( MooseX::XSAccessor::Trait::Attribute )],
28             },
29             role_metaroles => {
30             applied_attribute => [qw( MooseX::XSAccessor::Trait::Attribute )],
31             },
32             );
33             }
34              
35             sub is_xs {
36 37     37 1 97974 my $sub = $_[0];
37              
38 37 100 66     205 if ( blessed($sub) and $sub->isa( "Class::MOP::Method" ) ) {
    100          
39 1         5 $sub = $sub->body;
40             }
41             elsif ( not ref $sub ) {
42 44     44   7135 no strict "refs";
  44         112  
  44         4933  
43 1         3 $sub = \&{$sub};
  1         5  
44             }
45              
46 37         194 require B;
47 37         311 !! B::svref_2object( $sub )->XSUB;
48             }
49              
50             1;
51              
52             __END__
53              
54             =pod
55              
56             =for stopwords Auto-deref Mouse/Class::XSAccessor
57              
58             =encoding utf-8
59              
60             =head1 NAME
61              
62             MooseX::XSAccessor - use Class::XSAccessor to speed up Moose accessors
63              
64             =head1 SYNOPSIS
65              
66             package MyClass;
67            
68             use Moose;
69             use MooseX::XSAccessor;
70            
71             has foo => (...);
72              
73             =head1 DESCRIPTION
74              
75             This module accelerates L<Moose>-generated accessor, reader, writer and
76             predicate methods using L<Class::XSAccessor>. You get a speed-up for no
77             extra effort. It is automatically applied to every attribute in the
78             class.
79              
80             =begin private
81              
82             =item init_meta
83              
84             =end private
85              
86             The use of the following features of Moose attributes prevents a reader
87             from being accelerated:
88              
89             =over
90              
91             =item *
92              
93             Lazy builder or lazy default.
94              
95             =item *
96              
97             Auto-deref. (Does anybody use this anyway??)
98              
99             =back
100              
101             The use of the following features prevents a writer from being
102             accelerated:
103              
104             =over
105              
106             =item *
107              
108             Type constraints (except C<Any>; C<Any> is effectively a no-op).
109              
110             =item *
111              
112             Triggers
113              
114             =item *
115              
116             Weak references
117              
118             =back
119              
120             An C<rw> accessor is effectively a reader and a writer glued together, so
121             both of the above lists apply.
122              
123             Predicates can always be accelerated, provided you're using Class::XSAccessor
124             1.17 or above.
125              
126             Clearers can not be accelerated (as of current versions of Class::XSAccessor).
127              
128             =head2 Functions
129              
130             This module also provides one function, which is not exported so needs to be
131             called by its full name.
132              
133             =over
134              
135             =item C<< MooseX::XSAccessor::is_xs($sub) >>
136              
137             Returns a boolean indicating whether a sub is an XSUB.
138              
139             C<< $sub >> may be a coderef, L<Class::MOP::Method> object, or a qualified
140             sub name as a string (e.g. C<< "MyClass::foo" >>).
141              
142             This function doesn't just work with accessors, but should be able to detect
143             the difference between Perl and XS subs in general. (It may not be 100%
144             reliable though.)
145              
146             =back
147              
148             =head2 Chained accessors and writers
149              
150             L<MooseX::XSAccessor> can detect chained accessors and writers created
151             using L<MooseX::Attribute::Chained>, and can accelerate those too.
152              
153             package Local::Class;
154             use Moose;
155             use MooseX::XSAccessor;
156             use MooseX::Attribute::Chained;
157            
158             has foo => (traits => ["Chained"], is => "rw");
159             has bar => (traits => ["Chained"], is => "ro", writer => "_set_bar");
160             has baz => ( is => "rw"); # not chained
161            
162             my $obj = "Local::Class"->new;
163             $obj->foo(1)->_set_bar(2);
164             print $obj->dump;
165              
166             =head2 Lvalue accessors
167              
168             L<MooseX::XSAccessor> will detect lvalue accessors created with
169             L<MooseX::LvalueAttribute> and, by default, skip accelerating them.
170              
171             However, by setting C<< $MooseX::XSAccessor::LVALUE >> to true
172             (preferably using the C<local> Perl keyword), you can force it to
173             accelerate those too. This introduces a visible change in behaviour
174             though. L<MooseX::LvalueAttribute> accessors normally allow two
175             patterns for setting the value:
176              
177             $obj->foo = 42; # as an lvalue
178             $obj->foo(42); # as a method call
179              
180             However, once accelerated, they may I<only> be set as an lvalue.
181             For this reason, setting C<< $MooseX::XSAccessor::LVALUE >> to true is
182             considered an experimental feature.
183              
184             =head1 HINTS
185              
186             =over
187              
188             =item *
189              
190             Make attributes read-only when possible. This means that type constraints
191             and coercions will only apply to the constructor, not the accessors, enabling
192             the accessors to be accelerated.
193              
194             =item *
195              
196             If you do need a read-write attribute, consider making the main accessor
197             read-only, and having a separate writer method. (Like
198             L<MooseX::SemiAffordanceAccessor>.)
199              
200             =item *
201              
202             Make defaults eager instead of lazy when possible, allowing your readers
203             to be accelerated.
204              
205             =item *
206              
207             If you need to accelerate just a specific attribute, apply the attribute
208             trait directly:
209              
210             package MyClass;
211            
212             use Moose;
213            
214             has foo => (
215             traits => ["MooseX::XSAccessor::Trait::Attribute"],
216             ...,
217             );
218              
219             =item *
220              
221             If you don't want to add a dependency on MooseX::XSAccessor, but do want to
222             use it if it's available, the following code will use it optionally:
223              
224             package MyClass;
225            
226             use Moose;
227             BEGIN { eval "use MooseX::XSAccessor" };
228            
229             has foo => (...);
230              
231             =back
232              
233             =head1 CAVEATS
234              
235             =over
236              
237             =item *
238              
239             Calling a writer method without a parameter in Moose does not raise an
240             exception:
241              
242             $person->set_name(); # sets name attribute to "undef"
243              
244             However, this is a fatal error in Class::XSAccessor.
245              
246             =item *
247              
248             MooseX::XSAccessor does not play nice with attribute traits that alter
249             accessor behaviour, or define additional accessors for attributes.
250             L<MooseX::SetOnce> is an example thereof. L<MooseX::Attribute::Chained>
251             is handled as a special case.
252              
253             =item *
254              
255             MooseX::XSAccessor only works on blessed hash storage; not e.g.
256             L<MooseX::ArrayRef> or L<MooseX::InsideOut>. MooseX::XSAccessor is
257             usually able to detect such situations and silently switch itself off.
258              
259             =back
260              
261             =head1 BUGS
262              
263             Please report any bugs to
264             L<https://github.com/tobyink/p5-moosex-xsaccessor/issues>.
265              
266             =head1 SEE ALSO
267              
268             L<MooseX::XSAccessor::Trait::Attribute>.
269              
270             L<Moose>, L<Moo>, L<Class::XSAccessor>.
271              
272             =head1 AUTHOR
273              
274             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
275              
276             =head1 COPYRIGHT AND LICENCE
277              
278             This software is copyright (c) 2013, 2017, 2022 by Toby Inkster.
279              
280             This is free software; you can redistribute it and/or modify it under
281             the same terms as the Perl 5 programming language system itself.
282              
283             =head1 DISCLAIMER OF WARRANTIES
284              
285             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
286             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
287             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
288