Class-InsideOut
view release on metacpan or search on metacpan
Bug fixes:
- fixed tests for recent, XS-only Scalar::Util
Other:
- converted distribution management to Dist::Zilla
1.10 Mon Aug 24 20:44:46 EDT 2009
Bug fixes:
- changed method of calling Exporter::import() to avoid confusing DProf
- fixed detection of missing 'weaken' function in newer Scalar::Util
(fixes test t/15_no_weaken_fallback.t) (RT#47623)
Other:
- cleanup: eliminate test warning from bogus superclass in a test class
- docs: Noted that set_hooks aren't called by new() (RT#48106)
1.09 Fri Jan 4 18:42:41 EST 2008
- bugfix: allow use of upper or mixed case property accessors
(David Schmitt)
0.14 Thu Mar 16 23:07:22 EST 2006
- Fixed test bug where thread test wouldn't properly skip for Win32 Perl
5.6 (with ithreads enabled for pseudofork but no threads.pm)
- Improved handling of "die" in set_hook and get_hook callbacks
0.13 Fri Mar 10 10:32:08 EST 2006
- Test for Scalar::Util::weaken fallback had a bug that would fail on
Perl versions prior to 5.6. Fixed to be fully backwards compatible.
0.12 Wed Mar 8 21:58:58 EST 2006
- Added workaround for unavailable Scalar::Util::weaken; gives warning
about not running thread-safe; added missing weaken skips to thread/fork
test files
- property/public/private arguments are now validated. Property names must
be identifiers; Property options must be given as hash references;
Duplicate property names are not permitted.
- options argument checked for proper format; option values are checked
for validity
- register argument checked for blessed reference
t/05_forking.t
t/06_export_ok.t
t/07_synopsis_obj.t
t/08_DEMOLISH.t
t/09_foreign.t
t/10_storable_values.t
t/11_storable_refs.t
t/12_storable_hooks.t
t/13_options.t
t/14_accessor_hooks.t
t/15_no_weaken_fallback.t
t/16_property_argument_checking.t
t/17_option_argument_checking.t
t/18_register_argument_checking.t
t/19_storable_singleton.t
t/20_storable_singleton_error.t
t/21_optional_new.t
t/22_readonly.t
t/23_accessor_hooks_blessed.t
t/24_accessor_hooks_overloaded.t
t/25_accessor_hooks_typetiny.t
The hook must be a coderef, including blessed coderefs and overloaded
objects.
SEE ALSO
Programmers seeking a more full-featured approach to inside-out objects
are encouraged to explore Object::InsideOut. Other implementations are
also noted in Class::InsideOut::Manual::About.
KNOWN LIMITATIONS
Requires weak reference support (Perl >= 5.6) and Scalar::Util::weaken()
to avoid memory leaks and to provide thread-safety.
ROADMAP
Features slated for after the 1.0 release include:
* Adding support for Data::Dump::Streamer serialization hooks
* Adding additional accessor styles (e.g. get_name()/set_name())
* Further documentation revisions and clarification
lib/Class/InsideOut.pm view on Meta::CPAN
"new" => [ qw( new ) ],
"all" => [ @EXPORT_OK ],
"singleton" => [], # just a flag for import()
);
use Carp;
use Exporter;
use Class::ISA;
use Scalar::Util 1.09 qw( refaddr reftype blessed );
# Check for XS Scalar::Util with weaken() or warn and fallback
# syntax of error changed in Scalar::Util so we check both versions
BEGIN {
eval { Scalar::Util->import( "weaken" ) };
if ( $@ =~ /\AWeak references|weaken is only available/ ) {
warn "Scalar::Util::weaken unavailable: "
. "Class::InsideOut will not be thread-safe and will leak memory\n";
*weaken = sub { return @_ };
}
}
#--------------------------------------------------------------------------#
# Class data
#--------------------------------------------------------------------------#
my %PROP_DATA_FOR; # class => { prop_name => property hashrefs }
my %PUBLIC_PROPS_FOR; # class => { prop_name => 1 }
my %CLASS_ISA; # class => [ list of self and @ISA tree ]
lib/Class/InsideOut.pm view on Meta::CPAN
croak "Invalid argument '$_[0]' to register(): " .
"must be an object or class name"
}
}
else {
# register( REFERENCE/OBJECT, CLASSNAME )
$obj = shift;
bless $obj, shift; # ok to rebless
}
weaken( $OBJECT_REGISTRY{ refaddr $obj } = $obj );
return $obj;
}
#--------------------------------------------------------------------------#
# private functions for implementation
#--------------------------------------------------------------------------#
# Registering is global to avoid having to register objects for each class.
# CLONE is not exported but CLONE in Class::InsideOut updates all registered
# objects for all properties across all classes
lib/Class/InsideOut.pm view on Meta::CPAN
# for all properties, relocate data to the new id if
# the property has data under the old id
for my $prop ( @properties ) {
next unless exists $prop->{ $old_id };
$prop->{ $new_id } = $prop->{ $old_id };
delete $prop->{ $old_id };
}
# update the registry to the new, cloned object
weaken ( $OBJECT_REGISTRY{ $new_id } = $object );
_deregister( $old_id );
}
}
sub _check_options{
my ($opt) = @_;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
croak "Invalid options argument '$opt': must be a hash reference"
if ref $opt ne 'HASH';
lib/Class/InsideOut.pm view on Meta::CPAN
The hook must be a coderef, including blessed coderefs and overloaded objects.
=head1 SEE ALSO
Programmers seeking a more full-featured approach to inside-out objects are
encouraged to explore L<Object::InsideOut>. Other implementations are also
noted in L<Class::InsideOut::Manual::About>.
=head1 KNOWN LIMITATIONS
Requires weak reference support (Perl E<gt>= 5.6) and Scalar::Util::weaken() to
avoid memory leaks and to provide thread-safety.
=head1 ROADMAP
Features slated for after the 1.0 release include:
=over
=item *
lib/Class/InsideOut/Manual/Advanced.pod view on Meta::CPAN
CLONE hook, depending on demand.
B<Limitations:>
C<<< fork >>> on Perl for Win32 is emulated using threads since Perl
5.6. (See L<perlfork>.) As Perl 5.6 did not support C<<< CLONE >>>, inside-out objects
that use memory addresses (e.g. C<<< Class::InsideOut >>>) are not fork-safe for Win32
on Perl 5.6. Win32 Perl 5.8 C<<< fork >>> is supported.
The technique for thread-safety requires creating weak references using
C<<< Scalar::Util::weaken() >>>, which is implemented in XS. If the XS-version of
L<Scalar::Util> is not installed or if run on an older version of Perl without
support for weak references, C<<< Class::InsideOut >>> will issue a warning and
continue without thread-safety. Also, objects will leak memory unless manually
deregistered with a private function:
# destroying an object when weaken() isn't availalbe
Class::InsideOut::_deregister( $obj );
undef $obj;
=head1 SEE ALSO
=over
=item *
L<Class::InsideOut>
t/04_threaded.t view on Meta::CPAN
}
# don't run for Perl prior to 5.8 (with CLONE) (even if
# threads *are* configured)
if( $] < 5.008005 ) {
require Test::More;
Test::More::plan( skip_all =>
"thread support requires perl 5.8.5" );
}
# don't run without Scalar::Util::weaken()
eval "use Scalar::Util 'weaken'";
if( $@ =~ /\AWeak references are not implemented/ ) {
require Test::More;
Test::More::plan( skip_all =>
"Scalar::Util::weaken() is required for thread-safety" );
}
# don't run this at all under Devel::Cover
if ( $ENV{HARNESS_PERL_SWITCHES} &&
$ENV{HARNESS_PERL_SWITCHES} =~ /Devel::Cover/ ) {
require Test::More;
Test::More::plan( skip_all =>
"Devel::Cover not compatible with threads" );
}
t/05_forking.t view on Meta::CPAN
# skip if threads not available for some reasons
if ( ! $Config{useithreads} ) {
plan skip_all => "Win32 fork() support requires threads";
}
# skip if perl < 5.8
if ( $] < 5.008 ) {
plan skip_all => "Win32 fork() support requires perl 5.8";
}
# skip if Scalar::Util::weaken isn't available
eval "use Scalar::Util 'weaken'";
if( $@ =~ /\AWeak references are not implemented/ ) {
plan skip_all => "Win32 fork() support requires Scalar::Util::weaken()";
}
}
# Otherwise, we're going to run the tests.
plan tests => 10;
#--------------------------------------------------------------------------#
my $class = "t::Object::Animal";
my $subclass = "t::Object::Animal::Antelope";
t/11_storable_refs.t view on Meta::CPAN
use strict;
use lib ".";
BEGIN {
# don't run without Scalar::Util::weaken()
eval "use Scalar::Util 'weaken'";
if( $@ =~ /\AWeak references are not implemented/ ) {
require Test::More;
Test::More::plan( skip_all =>
"Can't test storable refs without Scalar::Util::weaken" );
}
}
use Test::More;
use Class::InsideOut ();
use Scalar::Util qw( refaddr reftype weaken isweak );
# Need Storable 2.04 ( relatively safe STORABLE_freeze support )
eval { require Storable and Storable->VERSION( 2.04 ) };
if ( $@ ) {
plan skip_all => "Storable >= 2.04 not installed",
}
sub check_version {
my ($class, $version) = @_;
eval { require $class and $class->VERSION($version) };
t/11_storable_refs.t view on Meta::CPAN
"... Charlie2 has Bob2 as a friend"
);
ok( $bob2->has_friend( $alice2 ),
"... Bob2 has Alice2 as a friend"
);
# storing Alice inside herself !!
push @$alice, $alice;
weaken( $alice->[0] );
ok( isweak( $alice->[0] ),
"Storing a weak reference to Alice inside Alice (!!)"
);
# freeze object
ok( $frozen = $s->{freeze}->( $alice ),
"Freezing Alice"
);
# thaw object
t/15_no_weaken_fallback.t view on Meta::CPAN
use lib ".";
use Test::More;
$|++; # keep stdout and stderr in order on Win32
# Devel::Cover doesn't seem to actually track coverage for the hacks
# used here, so we'll skip it.
if ( $ENV{HARNESS_PERL_SWITCHES} &&
$ENV{HARNESS_PERL_SWITCHES} =~ /Devel::Cover/ ) {
plan skip_all =>
"no_weaken_fallback tests not compatible with Devel::Cover";
}
# find what Scalar::Util we have
my $rc = system($^X, '-e', 'use Scalar::Util; Scalar::Util->VERSION(1.2303)');
if ( ! $rc ) {
plan skip_all =>
"Your Scalar::Util is XS only";
}
# Overload DynaLoader and XSLoader to fake lack of XS for Scalar::Util
t/15_no_weaken_fallback.t view on Meta::CPAN
{
local $^W = 1;
local $SIG{__WARN__} = sub { $warning = shift };
eval "require $class";
}
is( $@, q{},
"require $class succeeded without XS"
);
ok( $warning, "caught a warning" );
like( $warning, '/Scalar::Util::weaken/',
"Saw warning for Scalar::Util::weaken unavailable"
);
( run in 0.752 second using v1.01-cache-2.11-cpan-65fba6d93b7 )