Codebase list libclass-xsaccessor-perl / fresh-snapshots/main README.md
fresh-snapshots/main

Tree @fresh-snapshots/main (Download .tar.gz)

README.md @fresh-snapshots/mainraw · history · blame

[![Build Status](https://github.com/tsee/Class-XSAccessor/workflows/testsuite/badge.svg)](https://github.com/tsee/Class-XSAccessor/actions?query=workflow%3Atestsuite)
[![CPAN Version](https://badge.fury.io/pl/Class-XSAccessor.svg)](https://badge.fury.io/pl/Class-XSAccessor)

# NAME

Class::XSAccessor - Generate fast XS accessors without runtime compilation

# SYNOPSIS

```perl
package MyClass;

use Class::XSAccessor
    replace     => 1,   # Replace existing methods (if any)
    constructor => 'new',
    getters     => {
        get_foo => 'foo', # 'foo' is the hash key to access
        get_bar => 'bar',
    },
    setters => {
        set_foo => 'foo',
        set_bar => 'bar',
    },
    accessors => {
        foo => 'foo',
        bar => 'bar',
    },
    # "predicates" is an alias for "defined_predicates"
    defined_predicates => {
        defined_foo => 'foo',
        defined_bar => 'bar',
    },
    exists_predicates => {
        has_foo => 'foo',
        has_bar => 'bar',
    },
    lvalue_accessors => { # see below
        baz => 'baz', # ...
    },
    true  => [ 'is_token', 'is_whitespace' ],
    false => [ 'significant' ];

# The imported methods are implemented in fast XS.

# normal class code here.
```

As of version 1.05, some alternative syntax forms are available:

```perl
package MyClass;

# Options can be passed as a HASH reference, if preferred,
# which can also help Perl::Tidy to format the statement correctly.
use Class::XSAccessor {
    # If the name => key values are always identical,
    # the following shorthand can be used.
    accessors => [ 'foo', 'bar' ],
};
```

# DESCRIPTION

Class::XSAccessor implements fast read, write and read/write accessors in XS.
Additionally, it can provide predicates such as `has_foo()` for testing
whether the attribute `foo` exists in the object (which is different from
"is defined within the object").
It only works with objects that are implemented as ordinary hashes.
[Class::XSAccessor::Array](https://metacpan.org/pod/Class::XSAccessor::Array) implements the same interface for objects
that use arrays for their internal representation.

Since version 0.10, the module can also generate simple constructors
(implemented in XS). Simply supply the
`constructor => 'constructor_name'` option or the
`constructors => ['new', 'create', 'spawn']` option.
These constructors do the equivalent of the following Perl code:

```perl
sub new {
    my $class = shift;
    return bless { @_ }, ref($class) || $class;
}
```

That means they can be called on objects and classes but will not
clone objects entirely. Parameters to `new()` are added to the
object.

The XS accessor methods are between 3 and 4 times faster than typical
pure-Perl accessors in some simple benchmarking.
The lower factor applies to the potentially slightly obscure
`sub set_foo_pp {$_[0]->{foo} = $_[1]}`, so if you usually
write clear code, a factor of 3.5 speed-up is a good estimate.
If in doubt, do your own benchmarking!

The method names may be fully qualified. The example in the synopsis could
have been written as `MyClass::get_foo` instead
of `get_foo`. This way, methods can be installed in classes other
than the current class. See also: the `class` option below.

By default, the setters return the new value that was set,
and the accessors (mutators) do the same. This behaviour can be changed
with the `chained` option - see below. The predicates return a boolean.

Since version 1.01, `Class::XSAccessor` can generate extremely simple methods which
just return true or false (and always do so). If that seems like a
really superfluous thing to you, then consider a large class hierarchy
with interfaces such as [PPI](https://metacpan.org/pod/PPI). These methods are provided by the `true`
and `false` options - see the synopsis.

`defined_predicates` check whether a given object attribute is defined.
`predicates` is an alias for `defined_predicates` for compatibility with
older versions of `Class::XSAccessor`. `exists_predicates` checks
whether the given attribute exists in the object using `exists`.

# OPTIONS

In addition to specifying the types and names of accessors, additional options
can be supplied which modify behaviour. The options are specified as key/value pairs
in the same manner as the accessor declaration. For example:

```perl
use Class::XSAccessor {
    getters => {
        get_foo => 'foo',
    },
    replace => 1
};
```

The list of available options is:

## replace

Set this to a true value to prevent `Class::XSAccessor` from
complaining about replacing existing subroutines.

## chained

Set this to a true value to change the return value of setters
and mutators (when called with an argument).
If `chained` is enabled, the setters and accessors/mutators will
return the object. Mutators called without an argument still
return the value of the associated attribute.

As with the other options, `chained` affects all methods generated
in the same `use Class::XSAccessor ...` statement.

## class

By default, the accessors are generated in the calling class. The
the `class` option allows the target class to be specified.

# LVALUES

Support for lvalue accessors via the keyword `lvalue_accessors`
was added in version 1.08. At this point, **THEY ARE CONSIDERED HIGHLY
EXPERIMENTAL**. Furthermore, their performance hasn't been benchmarked
yet.

The following example demonstrates an lvalue accessor:

```perl
package Address;

use Class::XSAccessor {
    constructor => 'new',
    lvalue_accessors => { zip_code => 'zip' }
}

package main;

my $address = Address->new(zip => 2);
print $address->zip_code, "\n"; # prints 2
$address->zip_code = 76135; # <--- This is it!
print $address->zip_code, "\n"; # prints 76135
```

# CAVEATS

Probably won't work for objects based on _tied_ hashes. But that's a strange thing to do anyway.

Scary code exploiting strange XS features.

If you think writing an accessor in XS should be a laughably simple exercise, then
please contemplate how you could instantiate a new XS accessor for a new hash key
that's only known at run-time. Note that compiling C code at run-time a la [Inline::C](https://metacpan.org/pod/Inline::C)
is a no go.

Threading. With version 1.00, a memory leak has been **fixed**. Previously, a small amount of
memory would leak if `Class::XSAccessor`-based classes were loaded in a subthread without having
been loaded in the "main" thread. If the subthread then terminated, a hash key and an int per
associated method used to be lost. Note that this mattered only if classes were **only** loaded
in a sort of throw-away thread.

In the new implementation, as of 1.00, the memory will still not be released, in the same situation,
but it will be recycled when the same class, or a similar class, is loaded again in **any** thread.

# SEE ALSO

- [Class::XSAccessor::Array](https://metacpan.org/pod/Class::XSAccessor::Array)
- [AutoXS](https://metacpan.org/pod/AutoXS)

# AUTHORS

- [Steffen Müller](mailto:smueller@cpan.org)
- [chocolateboy](mailto:chocolate@cpan.org)

# COPYRIGHT AND LICENSE

Copyright (C) 2008-2020 by Steffen Müller

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8 or,
at your option, any later version of Perl 5 you may have available.