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

I have a shared object in perl, blessed as explained in http://perldoc.perl.org/threads/shared.html#OBJECTS. I would like to add to $self a reference to a hash returned by some subroutine (specifically, I would like something like: $self->{MY_JSON} = JSON->new->utf8->decode($my_json_text). The problem is I get `Invalid value for shared scalar` error, and I beleive this is because I am trying to add to my shared variable (`$self`) a reference to an unshared one. How can I share the multilevel hash reference returned by JSON->new->utf8->decode?

I tried:

my $my_json : shared = JSON->new->utf8->decode($my_json_text); $self->{MY_JSON} = $my_json;
thanks!

Replies are listed 'Best First'.
Re: adding a hash to a shared object
by Corion (Patriarch) on Aug 11, 2010 at 10:58 UTC

    I guess that you'll be far better off by sharing the data while it is still in string format instead of sharing it once it is decoded. Also, I think you need to explicitly share every level of a data structure.

    Honestly, I'm not sure what you try to accomplish by sharing the data structure. Maybe there is an easier way to accomplish what you want to do without sharing the structure, for example by serializing the structure through a Thread::Queue to many worker threads.

      Maybe I got it all wrong. I started working with objects but perhaps it's not necessary and I'm just over-complicating things.

      So let me describe the scenario (I probably should have asked for your advice about it earlier)

      My perl script is used to run some kind of a pipeline. I start by reading a JSON file with a bunch of parameters in it. I then do some work - mainly building some data structures needed later and calling external programs that generate some output files I keep references to.

      I usually use a subroutine for each of these steps. Each such subroutine will usually write some data to a unique place that no other subroutine writes to (i.e. a specific key in a hash) and reads data that other subroutines may have generated (when I sued an object I had a large $self with many keys).

      These steps can take a good couple of minutes if done sequentially, but most of them can be run in parallel with some simple logic of dependencies that I have described in an earlier post and I now know how to handle.

      What would you suggest? perhaps a simple script (no objects) with "global" shared variables?

      Thank you

        Pass all the data between your subroutines via Thread::Queue. Each subroutine can be its own thread that reads from one queue and writes to the next queue. That way you have no shared data at all.

Re: adding a hash to a shared object
by BrowserUk (Patriarch) on Aug 11, 2010 at 13:04 UTC
    I am trying to add to my shared variable (`$self`) a reference to an unshared one. How can I share the multilevel hash reference returned by JSON->new->utf8->decode?

    Have you looked at threads::shared::shared_clone()?

    But, like Corion, I think that most of your difficulties are arising because you are approaching threading your problem from the wrong direction. However, as you have yet to either describe the actual problem in any detail, or post the actual code you are using, we can only give wishy washy answers to your specific questions.

    I suspect that if you would describe the overall problem in sufficient detail, there is probably a better way of approaching it that would avoid the problems you are encountering.


    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.
      I suspect that if you would describe the overall problem in sufficient detail, there is probably a better way of approaching it that would avoid the problems you are encountering. I fully agree. Wasn't this enough adding a hash to a shared object?
        Wasn't this enough

        Not really. The only question you ask there is: "How can I share the multilevel hash reference returned by JSON->new->utf8->decode?". Which I answered with a reference to shared_close().

        But that doesn't give us the possibility of suggesting a different approach to achieving your actual goal, rather than just telling you how to implement one small part of your current approach to achieving that goal.

        I'd like to see you post a standalone, single-threaded program with some sample data, that achieves the overall goal. We could then explore the potential for gains through threading, and perhaps, offer an implementation that achieves that, whilst playing to the strengths and avoiding the known weaknesses in the Perl threading model.

        I'm fairly adept with threading in general and ithreads in particular, and I strongly recommend starting from a working single threaded program as a base.


        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.