Thread

Posted on Thu Oct 25 00:14:52 2007 by buchet
Storing objects inside of shared objects
As mentioned in BUGS AND LIMITATIONS it is not possible to store objects inside of shared objects. I discovered that this not true for classical hash blessed objects stored in an Object::InsideOut container. It seems to me that the problem is the reference counter which demolish the InsideOut object inside of the container too early.
package Container; use threads; use threads::shared; { use Object::InsideOut ':SHARED'; my @objects : Field : All(objects) : Type(ARRAY_ref); sub object { my ( $self, $object ) = @_; return $self->objects()->[-1] unless $object; die 'parameter should be able to do data' unless ( ref($object) && $object->can('data') ); $self->set( \@objects, [] ) unless ( ref $objects[$$self] eq 'ARRAY' ); push @{ $self->objects() }, $object; return $self->objects()->[-1]; } } package Insideout; use threads; use threads::shared; { use Object::InsideOut ':SHARED'; my @data : Field : All(data); } package HashBlessed; use threads; use threads::shared; sub new { my ( $class, $args ) = @_; my $self : shared; $self = &share( {} ); bless $self, $class; if ( ref $args eq 'HASH' && exists $args->{data} ) { $self->{data} = $args->{data}; } return $self; } sub data { my ( $self, $val ) = @_; if ( defined $val ) { lock $self; $self->{data} = $val; } return $self->{data}; } my $io = Insideout->new( { data => 'insideout' } ); my $hb = HashBlessed->new( { data => 'hashblessed' } ); my $container = Container->new(); $container->object($hb); warn('hash bless object has lost his data') unless ( $container->objects()->[-1]->data() eq 'hashblessed' ); $container->object($io); warn('inside out object has lost his data') unless ( $container->objects()->[-1]->data() eq 'insideout' ); $container->object($hb); warn('hash bless object has lost his data') unless ( $container->objects()->[-1]->data() eq 'hashblessed' );
Am I on the right path?
Direct Responses: 6334 | Write a response
Posted on Thu Oct 25 20:24:47 2007 by jdhedden in response to 6325
Re: Storing objects inside of shared objects
> As mentioned in BUGS AND LIMITATIONS it is not possible
> to store objects inside of shared objects.

Well, not exactly. It actually says:
There are bugs associated with L<threads::shared> that may prevent you from using foreign inheritance with shared objects, or storing objects inside of shared objects.
The operative word being may. If you can get it to work, then fine. However, as your test shows, it doesn't always work (e.g., storing OIO objects inside other OIO objects).

> It seems to me that the problem is the reference
> counter which demolish the InsideOut object inside
> of the container too early.

I don't know the exact cause (or I would get it fixed ;), but the problem does lie in the XS code for threads::shared. There is a bug report against it, but I don't know when (if ever) it will get fixed.
Direct Responses: 6336 | Write a response
Posted on Fri Oct 26 17:21:59 2007 by jdhedden in response to 6334
Re: Storing objects inside of shared objects
I looked into this a bit more. The reason your HashBlessed class seems to work is that it does not have a DESTROY subroutine. If you add:
sub DESTROY { delete(shift->{data}); }
you'll find that HashBlessed fails, too. This shows that shared objects stored inside shared structures get destroyed inappropriately. As I stated before, this is a threads::shared bug. The following illustrates this (without using OIO):
#!/usr/bin/perl use strict; use warnings; use threads; use threads::shared; package Jar; { my @jar :shared; sub new { bless(&threads::shared::share({}), shift); } sub store { my ($self, $cookie) = @_; push(@jar, $cookie); print("JAR : Cookie stored\n"); return $jar[-1]; # BUG: The cookie is destroyed here } } package Cookie; { my $destruction_count = 0; sub new { bless(&threads::shared::share({}), shift); } sub DESTROY { $destruction_count++; print("COOKIE: destruction count = $destruction_count\n"); } } package main; MAIN: { my $jar = Jar->new(); my $cookie = Cookie->new(); print("MAIN : Storing cookie\n"); $jar->store($cookie); print("\nMAIN : Cookie should not have been destroyed yet\n"); print("\nMAIN : Exiting scope\n") } print("\nDONE\n");
which outputs:
MAIN : Storing cookie JAR : Cookie stored COOKIE: destruction count = 1 MAIN : Cookie should not have been destroyed yet MAIN : Exiting scope COOKIE: destruction count = 2 DONE
Direct Responses: 6340 | Write a response
Posted on Fri Oct 26 21:15:51 2007 by buchet in response to 6336
Re: Storing objects inside of shared objects
Many thanks for your replies and investigations. I will take your example code to write a test case for the threads::shared module. Because I'm not familiar with xs code at all, I have not much hope to find a solution for this problem, but I don't want to give up without a try.
Direct Responses: 6419 | Write a response
Posted on Thu Nov 8 18:00:45 2007 by jdhedden in response to 6340
Re: Storing objects inside of shared objects
I was able to come up with a fix to the Perl interpreter for this.

If you want to store shared objects inside other shared objects, you'll need to get Perl 5.10.0 (either build the lastest snapshot yourself, or wait for an official release), and then upgrade threads::shared to version 1.15 or later.
Direct Responses: 6486 | Write a response
Posted on Tue Nov 20 21:48:07 2007 by buchet in response to 6419
Re: Storing objects inside of shared objects
Sorry for the late reply; I build perl 5.10 and upgrade threads::shared to 1.15. Everything now works fine. Many thanks for your help.
Write a response