in reply to Re^3: a question on sharing data structures across threads
in thread a question on sharing data structures across threads

hmm... i did what you advised me to do, but with a remarkable result:
my %el : shared = ( 'data' => $scalar_data, 'atime' => time, 'deleted' => 0, 'modified' => 0 ); $planets{$some_id} = \%el; lock $planets{$some_id}; # results in an error: "lock can only be used on shared values."
--------------------------------
masses are the opiate for religion.

Replies are listed 'Best First'.
Re^5: a question on sharing data structures across threads
by BrowserUk (Patriarch) on Oct 09, 2007 at 05:42 UTC

    The problem is not with what you have done, but rather a variation on the following bug as noted in the BUGS section of the threads::shared POD:

    share() allows you to share $hashref->{key} without giving any error message. But the $hashref->{key} is not shared, causing the error ``locking can only be used on shared values'' to occur when you attempt to lock $hashref->{key}.

    What that really means is that you cannot use lock on an element of a hash or array. Both the following attempts to lock an individual element fail in the same way:

    #! perl -slw use strict; use threads; use threads::shared; my %h :shared = ( x => 1 ); lock $h{ x }; my @a :shared = 1 .. 4; lock $a[ 1 ];

    The best you can do is lock the entire hash or array--with all the potential performance hit that might entail. The hit can be minimised by confining the lock to as small a scope as possible. On a single cpu, this will in most cases ensure that the lock does not get persist long enough to be interupted by a task switch and so no penalty will result. It doesn't prevent the penalty on a multi-cpu machine.

    Yes. I know it is ludicrous, but no one is listening.


    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^5: a question on sharing data structures across threads
by BrowserUk (Patriarch) on Oct 09, 2007 at 07:14 UTC

    Here's what might be considered a work-around for the limitation:

    #! perl -slw use strict; use threads; use threads::shared; my $some_id = 1; ## Make the scalar shared my $scalar_data :shared = 'fred'; my %planets :shared; my %el :shared = ( 'data' => \$scalar_data, ## reference to shared scalar 'atime' => time, 'deleted' => 0, 'modified' => 0 ); $planets{$some_id} = \%el; ## Lock the shared hash (%el) by indirection lock %{ $planets{$some_id} }; ## Or lock the data itself via indirection lock ${ $planets{ $some_id }{ data } };

    Seems a tad hookey, but it does allow you to lock the relevant sub-hash or piece of data without requiring you to lock the entire top-level hash.


    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.
      splendid idea, thx again! (although i must confess that next time i better read the fine manual to the end... ;-) )

      update, some minutes later: and if one thinks about it, the answer is pretty simple: the reference can't be locked, because it's not being shared - but the data it refers to.

      --------------------------------
      masses are the opiate for religion.