![]() |
Threads and OO Question
I have a peculiar problem with threads on Perl 5.8 (activestate on Win32)
My sample code is below, however, the problem is basically that if I run this under the debugger then if "works" as expected. Works in this case defined as some output goes to stdout. However, if I simply run the program from the command line, then I only get output from the thread running "MyPackage->start"... There is no output from the main thread. Any ideas why (does it happen to anyone else? Linux?) Is this to do with one of the threads grabbing stdout and the other not being able to access it? Secondly is this the "right" way to do thread programming? The "problem" I am trying to solve is to have the main start thread showing a GUI interface, where the MyPackage class is then a worker class which goes off and does something. Then the GUI will periodically access the properties of "MyPackage" to determine state and progress (and update the GUI). FWIW, there is a deliberate attempt to keep the two processes seperate hence not relying on the any abilities the GUI toolkit might provide to do background processing. Thanks Ed W >>>>>>>>>>>>>>>>>>>>>>>>>>>> use threads; use threads::shared; use strict; package MyPackage; my $counter : shared; $counter = 0; sub new { my $class = shift; my $this = {COUNTER => 0}; threads::shared::share($this->{COUNTER}); $counter = 0; return bless($this, $class); } sub start { my $this = shift; while (1) { $counter += 1; $this->{COUNTER} += 1; sleep 1; print STDOUT "In Counter: $counter \r\n"; } } sub getCounter { my $this = shift; return $this->{COUNTER}; # return $counter; } package main; sub MainLoop { my $a; my $a = MyPackage->new(); my $thr = threads->new(sub{$a->start();}); sleep 1; while (1) { my $count = $a->getCounter(); print STDOUT $count; sleep 1; } my @ReturnData = $thr->join; print "Thread returned @ReturnData"; } MainLoop(); |
Re: Threads and OO Question
"Edward Wildgoose" <Ed+nospam@ewildgoose.demon.co.uk@> wrote in message news:<yWTib.222522$p36.2183344@news.easynews.com>. ..
> I have a peculiar problem with threads on Perl 5.8 (activestate on Win32) > It's not threads, it's io buffering Add $| = 1; to the top of the program. > My sample code is below, however, the problem is basically that if I run > this under the debugger then if "works" as expected. Works in this case > defined as some output goes to stdout. > |
Re: Threads and OO Question
> > I have a peculiar problem with threads on Perl 5.8 (activestate on
Win32) > It's not threads, it's io buffering > > Add > > $| = 1; Bah! Yep, fixes everything! Can anyone point me to any other references on the new perl threads. I have read the man pages, and perlthrtut. I'm basically confused as to how to share variables between threads when the variable to be shared is a class. I'm aware this is fairly limited at the moment, but advice on how to make something like the below share variables correctly would be appreciated: Thanks, Ed W <scribble mode on> package main; my $worker = Worker->new(); my $thr = threads->new(sub{$worker->start();}); while (1) { my $stats = $worker->CheckStats(); useful_function( $stats->Do_Something_With_Object() ); } ############################## package Worker; sub new { my $class; return bless( {Stats => MyStats->new(), $class} } sub start { do_something(); } sub CheckStats { my $this; return $this->{Stats}; } #################### package MyStats; sub new { my $class; my $self = { bytes_in => 0, bytes_out => 0}; return bless($self, $class); } sub increment { etc } ....etc... |
Re: Threads and OO Question
> Can anyone point me to any other references on the new perl threads. I
have > read the man pages, and perlthrtut. I'm basically confused as to how to > share variables between threads when the variable to be shared is a class. > I'm aware this is fairly limited at the moment, but advice on how to make > something like the below share variables correctly would be appreciated: Partly answering my own question, it seems I can do the following: package MyStats; use threads::shared; sub new { my $class = shift; my $this = { bytes_in => 0, bytes_out => 0}; share($this); return bless($this, $class); } sub increment { my $this = shift; $this->{bytes_in} += shift; $this->{bytes_out} += shift; } From reading the documentation it wasn't clear that this was valid, or even correct (ie sharing the whole $this variable). Presumably this breaks if anything in the $this is either a) not a scalar, or b) not itself shared? Is there a more in-depth tutorial on this anywhere? It's kind of slow going having to write all these experimental bits of code to test stuff out first... (yeah, yeah, thread safe programming isn't supposed to be easy. I know, I know!) Thanks all Ed W |
Re: Threads and OO Question
"Edward Wildgoose" <Ed+nospam@ewildgoose.demon.co.uk@> wrote in message news:<9g9jb.2951223$Bf5.402549@news.easynews.com>. ..
> read the man pages, and perlthrtut. I'm basically confused as to how to > share variables between threads when the variable to be shared is a class. > > > <scribble mode on> > > package main; > > my $worker = Worker->new(); > my $thr = threads->new(sub{$worker->start();}); > while (1) { > my $stats = $worker->CheckStats(); > useful_function( $stats->Do_Something_With_Object() ); > } > > ############################## > package Worker; > > sub new { > my $class; > return bless( {Stats => MyStats->new(), $class} > } > Good question, I think. Maybe Arthur Bergman knows the answer. Do you have to share the class, or could you create a hash containing the data you want shared and share the hash? I say this because the docs on threads::shared (have you looked at threads::shared?) says that " bless is not supported on shared references. In the current version, bless will only bless the thread local reference and the blessing will not propagate to the other threads. This is expected to be implemented in a future version of Perl." |
Re: Threads and OO Question
> Good question, I think. Maybe Arthur Bergman knows the answer.
Sorry for my ignorance. Who is this person? Aha, google turns up "who" he is, but does he run a web page of useful info? (Anyone?) > Do you have to share the class, or could you create a hash containing > the data you want shared and share the hash? Nope, I just learned to use classes on Perl and I went wild... However, this then brings us full circle back to the problem. In the main thread how do I talk back to the worker thread in order to ask it to populate the shared hash? (I want to avoid nasty IPC stuff since I already wrote a socket communicator to the other process and I'm trying this method to avoid all that junk!) Because it seems to me that if the main thread calls some function, say, "getSomeInternalState", then this function cannot access the non-shared objects in order to populate the shared hash.... So if the worker thread is using shared hashes to proxy data back to the main thread then I might as well not bother with my Statistics encapsulation class at all since it's just a duplication... (Did that make any sense?) Yes, I can use semaphores to communicate to the worker process and get it to populate the shared hash, but so much nicer if I could just share the internal state object in the first place! > I say this because the docs on threads::shared (have you looked at > threads::shared?) says that > > " bless is not supported on shared references. In the current version, > bless will only bless the thread local reference and the blessing will > not propagate to the other threads. This is expected to be implemented > in a future version of Perl." Yeah, agree. However, see my other post because that code works on Activestate 5.8 (whatever the latest is as of today. build 806?) I have included the whole test script below: ....Should this work? Does it work under linux...? What the heck is going on...? Help! Thanks all Ed W >>>>>>>>>>>>>>>>>>>>>>>> use threads; use strict; package MyStats; use threads::shared; sub new { my $class = shift; my $this = { bytes_in => 0, bytes_out => 0}; share($this); return bless($this, $class); } sub increment { my $this = shift; $this->{bytes_in} += shift; $this->{bytes_out} += shift; } package MyPackage; use threads::shared; my $counter : shared; sub new { my $class = shift; my $this = {STATS => MyStats->new()}; share($this->{STATS}); return bless($this, $class); } sub start { my $this = shift; while (1) { $counter += 1; $this->{STATS}->increment(1,2); sleep 1; print STDOUT "In Counter: $counter \r\n"; } } sub getCounter { my $this = shift; return $this->{STATS}; # return $counter; } package main; use threads::shared; sub MainLoop { $| = 1; my $a; my $a = MyPackage->new(); my $thr = threads->new(sub{$a->start();}); sleep 1; while (1) { my $count = $a->getCounter(); print STDOUT $count; sleep 1; } my @ReturnData = $thr->join; print "Thread returned @ReturnData"; } MainLoop(); |
Re: Threads and OO Question
"Edward Wildgoose" <Ed+nospam@ewildgoose.demon.co.uk@> wrote in message news:<TMfjb.6107219$mA4.867092@news.easynews.com>. ..
> > Good question, I think. Maybe Arthur Bergman knows the answer. > > Sorry for my ignorance. Who is this person? Aha, google turns up "who" he > is, but does he run a web page of useful info? (Anyone?) > Oh, he wrote the threads routines in 5.8, I think... > However, this then brings us full circle back to the problem. In the main > thread how do I talk back to the worker thread in order to ask it to > populate the shared hash? (I want to avoid IPC stuff since I already Well, if what you have works, I guess it's okay, but watch out for race conditions. Maybe one safe way is to create a flattened scalar representation of the object--kind of like when you want to save an object to disk--and pass that scalar via Thread::Semaphore? However I've never done this, so I'm out of ideas. |
| All times are GMT. The time now is 11:07 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.