Class-InsideOut

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    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)

Changes  view on Meta::CPAN


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

MANIFEST  view on Meta::CPAN

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

README  view on Meta::CPAN


    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.299 second using v1.01-cache-2.11-cpan-65fba6d93b7 )