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

I have a very basic question (i think) i just can't get my PHP mind wrapped around it.

I would like to initialize an array with objects, and i want to interact with those objects from both the main thread as the child threads.
our %test; %test{item1} = new Person("..", "..", ".."); %test{item2} = new Person("..", "..", "..");
However the above code does not work as expected.

What i would like to accomplish:
- Create the hash at application startup.
- Use the objects' functions in all threads

Meaning i would like to "share" the object and its values among threads. Is that even possible?

Replies are listed 'Best First'.
Re: Global objects?
by moritz (Cardinal) on May 07, 2008 at 14:10 UTC
    If you access a hash item, the sigil changes from % to $:
    our %test; $test{item1} = Person->new("...", ...); $test{item2} = Person->new("...", ...);
    Regarding the threads: I don't really know. You can use threads::shared, but I don't know if that works for objects. Maybe the threads tutorial is a good starting place for you.
Re: Global objects?
by samtregar (Abbot) on May 07, 2008 at 16:00 UTC
    You can't do that. Perl threads can't share objects, at least they couldn't the last time I played with them. Instead of sharing objects Perl threads typically communicate by passing messages in shared arrays and hashes. For example, check out the article I wrote about building a multi-threaded elevator simulator in Perl:

    http://www.perl.com/pub/a/2002/09/04/threads.html

    But perhaps more importantly, why are you using Perl threads? I think it's fair to say they're not very appropriate for a Perl beginner and that most experts don't use them either.

    -sam

      here is my current code (which works). Don't know about mem leaks however...
      #!/usr/bin/perl -w use strict; # Amen use threads; use threads::shared; #-------------------------------------------------- # Application includes #-------------------------------------------------- use person; #-------------------------------------------------- # Forward declarations #-------------------------------------------------- sub doTemp1; sub doTemp2; sub doQuit; #-------------------------------------------------- # Local variables #-------------------------------------------------- our $intDelay : shared; # One-wire delay our $blnRunning : shared; # Signal boolean our $intThreadCount : shared; # Holds the number of threads active our %hshSensors : shared; # Sensor hash our $OWFS : shared; # Main application our $OWFS_MOUNT : shared; # Mounting point $SIG{HUP} = \&doQuit; $SIG{INT} = \&doQuit; $SIG{TERM} = \&doQuit; $SIG{CHLD} = 'IGNORE'; # Ignore child processes to prevent zomb +ies $OWFS = "/opt/owfs/bin/owfs"; $OWFS_MOUNT = "/var/1-wire"; #-------------------------------------------------- # Start application #-------------------------------------------------- $intDelay = 5; $intThreadCount = 0; $blnRunning = 1; # Start polling `echo 1 > $OWFS_MOUNT/simultaneous/voltage`; `echo 1 > $OWFS_MOUNT/simultaneous/temperature`; # Start thread for monitoring threads->new(\&doTemp, "Temperature 1", "10.D76B5A010800", 30, 0.2, "" +); threads->new(\&doTemp, "Temperature 2", "10.FB865A010800", 25, 0.2, "" +); # Just something to keep the script rolling in the background while (1) { sleep 3600; }; #-------------------------------------------------- # Thread sub sub doTemp { my ($strTitle, $strDevice, $dblNominal, $dblHysteris, $strStatus) += @_; my ($dblCurrent, $dblHigh, $dblLow); # Increment thread count $intThreadCount++; # Initialize values $dblCurrent = 0; $dblHigh = ($dblNominal + $dblHysteris); $dblLow = ($dblNominal - $dblHysteris); # Start main loop while ($blnRunning) { # Poll sensor $dblCurrent = `cat /var/1-wire/uncached/$strDevice/temperature +`; $dblCurrent =~ s/^\s+//; $dblCurrent =~ s/\s+$//; if ($dblCurrent) { if ($dblCurrent >= $dblHigh) { $strStatus = "TOO HOT ($dblCurrent / $dblHigh)"; } elsif ($dblCurrent <= $dblLow) { $strStatus = "TOO COLD ($dblCurrent / $dblLow)"; } else { $strStatus = "WITHIN RANGE ($dblCurrent)"; } # Dump data print "-> ($intThreadCount) $strTitle: $strStatus\n"; } sleep $intDelay; } # Decrement thread count $intThreadCount--; # Bail thread print "-> Polling of $strTitle stopped.\n"; } # Closes current server and bails out sub doQuit() { $blnRunning = 0; # Close threads which are running print "-> Waiting for destruction\n"; while ($intThreadCount > 0) { sleep 1; } print "-> Server destroyed\n"; exit; }
        I would question the need to use threads for this project. As far as I can see, the threads merely read what appears to be a 1-line file, and print, for each loop. There does not seem to be any "event" the thread waits on, other than a pre-specified timer.

        If this is an exercise (which is a laudable goal), I would approach using the threads differently.

        Avoid shared variables unless absolutely necessary. The only thing the threads need to be told is when to quit. You can pass that information using a Thread::Queue. Any data collected by the thread can be returned by the same mechanism. Working thread code using Queues, is available here.

        Each thread would read the queue in NON-BLOCKING mode, and quit if a message is received.

        The main thread would queue in THREADCOUNT messages, when it was time to quit.

        You also had additional requirements (in a separate post). If thresholds are breached, you can use the same thread to communicate the breach back to the main thread. That would then perform the appropriate action. This way, the thread code can be clean, and minimal.

        I would also suggest you let perl read the files, instead of doing "CAT".

             "How many times do I have to tell you again and again .. not to be repetitive?"

      Well, to be honest; The reading of the sensors happens in an uncached way. The reading takes about 1-2 seconds to complete, therefore i thoughd i'd fire a thread for each sensor. This way even though i have multiple sensors; it won't delay the script noticably.

      I've read your article today (briefly) i'll look into it more in depth right away! Thanx!

      p.s. i am using 5.8.8

        You might want to check out POE. This is the sort of task it is really great at.

        Of course POE isn't usually the first thing one throws at a Perl newbie. But you seem to be handling threads OK...


        TGI says moo