learnedbyerror has asked for the wisdom of the Perl Monks concerning the following question:

Oh Monks, I bring to you a riddle. When is_shared, not shared?

I have a threaded program in which I create a shared hash in main:

use threads qw(stringify); use threads::shared; my %contacts : shared;

I load a hashref into the hash in a sub-routine sharing each level as such:

$contacts{$contact} = &share( {} ); share( $contacts{$contact}{'a'} ); share( $contacts{$contact}{'inc_dnd'} ); share( $contacts{$contact}{'lock'} ); $contacts{$contact}{'a'} = 1; $contacts{$contact}{'inc_dnd'} = &share( {} ); $contacts{$contact}{'lock'} = 0;

In a thread, I try to execute

lock( $contacts{$user_id} );

I receive the following error

lock can only be used on shared values at get_contacts_pool_photos.pl line 170.

However, if I run the program in the debugger I can verify that I can access the hash and that it contains the data that I expect

DB<2> print Dumper $contacts{$user_id} $VAR1 = { 'inc_dnd' => {}, 'a' => '1', 'lock' => '0', 'd' => '/tmp' };

Futhermore, if I check to see if the variable is shared, I find that it is.

170: lock( $contacts{$user_id} ); DB<2> print is_shared($contacts{$user_id}) 226839368 DB<3> n lock can only be used on shared values at get_contacts_pool_photos.pl +line 170. at get_contacts_pool_photos.pl line 170 main::get_contacts_pool_photos() called at get_contacts_pool_p +hotos.pl line 93

So Monks, I ask, is it shared or not?

How should I fix my problem?

Thanks in advance for your guidance.

lbe

Replies are listed 'Best First'.
Re: thread::shared - shared but not shared?
by BrowserUk (Patriarch) on Sep 25, 2011 at 18:49 UTC

    Try it this way:

    #! perl -slw use strict; use threads; use threads::shared; my %h :shared; $h{ 1 } = &share( {} ); $h{1}{2} = 3; { lock %{ $h{1} }; ## <<<< async { print "2:Waiting for lock"; lock %{ $h{1} }; print "2:lock acquired"; $h{1}{2} = 10; print '2:lock released'; }->detach; sleep 2; } print "1:Waiting for lock"; lock %{ $h{1} }; print $h{1}{2}; __END__ c:\test>junk70 2:Waiting for lock 1:Waiting for lock 2:lock acquired 2:lock released 10

    It shouldn't be necessary, but it does work.


    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: thread::shared - shared but not shared?
by zentara (Cardinal) on Sep 25, 2011 at 19:21 UTC
    How should I fix my problem? lock( $contacts{$user_id} );

    I receive the following error lock can only be used on shared values at get_contacts_pool_photos.pl line 170.

    Some thoughts, as I see a similar problem when seting up hashes for Tk programs.

    My guess is that since you already declared second level hash elements, the first key to the hash gets a value that is another subhash. Its a common error in setting up deep hashes that gives a common error "Can't use string ("1") as a HASH ref while "strict refs"" in conventional programs.

    When you have

    $contacts{$contact} = &share( {} ); share( $contacts{$contact}{'a'} ); share( $contacts{$contact}{'inc_dnd'} ); share( $contacts{$contact}{'lock'} ); $contacts{$contact}{'a'} = 1; $contacts{$contact}{'inc_dnd'} = &share( {} ); $contacts{$contact}{'lock'} = 0; [download] In a thread, I try to execute lock( $contacts{$user_id} );
    Because of the way you have the hash's first key setup, $contacts{$user_id} evaluates to a hashref, not a scalar.

    You might try

    share( $contacts{$contact}{'user_id'} );
    or you can verify in your code by the threads:shared method
    is_shared ( $contacts{$user_id} )

    I run into this problem all the time with hashes in Tk, and that is what I do, but there may be better solutions.


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh