Threads and OO Question

Discussion in 'Perl Misc' started by Edward Wildgoose, Oct 14, 2003.

  1. 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();
    Edward Wildgoose, Oct 14, 2003
    #1
    1. Advertising

  2. Edward Wildgoose

    Bill Guest

    "Edward Wildgoose" <@> wrote in message news:<yWTib.222522$>...
    > 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.
    >
    Bill, Oct 14, 2003
    #2
    1. Advertising

  3. > > 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...
    Edward Wildgoose, Oct 15, 2003
    #3
  4. > 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
    Edward Wildgoose, Oct 15, 2003
    #4
  5. Edward Wildgoose

    Bill Guest

    "Edward Wildgoose" <@> wrote in message news:<9g9jb.2951223$>...

    > 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."
    Bill, Oct 15, 2003
    #5
  6. > 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();
    Edward Wildgoose, Oct 15, 2003
    #6
  7. Edward Wildgoose

    Bill Guest

    "Edward Wildgoose" <@> wrote in message news:<TMfjb.6107219$>...
    > > 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.
    Bill, Oct 16, 2003
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nick Marden
    Replies:
    0
    Views:
    1,064
    Nick Marden
    Jan 17, 2004
  2. yoda
    Replies:
    2
    Views:
    424
    =?utf-8?Q?Bj=C3=B6rn_Lindstr=C3=B6m?=
    Aug 1, 2005
  3. threads without threads

    , Aug 27, 2004, in forum: C Programming
    Replies:
    4
    Views:
    389
    William Ahern
    Aug 27, 2004
  4. Pedro Pinto

    Java Threads - Get running threads

    Pedro Pinto, Apr 8, 2008, in forum: Java
    Replies:
    2
    Views:
    1,415
    Arne Vajhøj
    Apr 9, 2008
  5. Une bévue
    Replies:
    0
    Views:
    137
    Une bévue
    Jun 14, 2006
Loading...

Share This Page