in reply to Re^2: Cloning shared hashref
in thread Cloning shared hashref

Use this:

use threads; use threads::shared; use Data::Dumper; sub clone { my $ref = shift; my $type = ref $ref; if( $type eq 'HASH' ) { return { map clone( $_ ), %{ $ref } }; } elsif( $type eq 'ARRAY' ) { return [ map clone( $_ ),@{ $ref } ]; } elsif( $type eq 'REF' ) { return \ clone( $$ref ); } else { return $ref; } } my $x :shared = shared_clone({ a => 'Foo', b => 'Bar' }); my $z = clone( $x ); print Dumper( $z );

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^4: Cloning shared hashref
by menth0l (Monk) on Jan 21, 2011 at 08:12 UTC
    Thanks. I wrote something similiar by myself but i hoped i would find somthing faster than pure perl cloning i.e. XS-implementation...

      Actually, I think that a pure perl solution is both the right and probably fastest solution to this.

      The problem with the XS implementations is that they are trying to create exact duplicates of the original structures, including any attached magic. Their problem with shared structures is that they were implemented before the shared magic was, and they've not been updated to handle it.

      But for your purpose, you need to explicitly remove that shared magic, which the pure perl cloning does. But as it doesn't have to try and replicate that magic and all the structures and possibilities associated with it, it will likely be faster than an XS implementation that did.

      Which given that you don't want it, is a win-win.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re^4: Cloning shared hashref
by jwba (Novice) on Mar 16, 2011 at 21:43 UTC
    I ran in exactly the same problem, I wanted to serialize a shared variable with YAML::XS. I reversed the shared_clone function and named it unshared_clone. The advantage is that references stay references (less memory consumption) and circular references don't blow up your script. I put it on github https://github.com/jwba/threads-shared-util.

      Could I ask you to explain the program requirements that led to the need for this routine and its particular feature set?

        Sure. I was running some functions in separate threads, returning graph-like structures (feature annotations of genome data), e.g.

        my $gene = { lots => 'of', data => 'entries' }; my $transcript = { 'even' => 'more', data => 'entries', gene => $gene +}; $gene->{transcript} = [ $transcript ];

        I put everything in a result queue of type Thread::Queue. I dequeue and freeze the results to a YAML file after the program finishes, so that I don't have to calculate everything again and again. Unfortunately, Thread::Queue does a shared_clone on everything one throws at it.

        This fact leads to the mentioned 'program requirements':

        1. Handle circular references
        2. Save some space with reusing references
        I hope this answers your question.