Perl threads in Object Oriented code

E

Eric

Hello,

I have a Perl script that utilizes Perl threads to run a function
(time) on a list of entities. Using Perl threads will allow the code
to run in parallel (as opposed to serially) and therefore minimize the
time it takes to run through the list.

The code does something similar to what the following code is doing:

============= Perl script =============

#!/usr/bin/perl

use strict;
use warnings;

use threads;
use threads::shared;

my @clocks = ("clock1", "clock2", "clock3");

foreach my $clock (@clocks) {
my $thr = threads->new(\&get);
sleep 1;
}

for my $t (threads->list()) {
my $result = $t->join;
}

sub get {
my $time = shift;
$time = time();
print STDOUT "The time is: $time\n";
return;
}
=======================================

Now, I want to get this script working in object oriented code. The
following scripts (plagiarized from a Perl book for the sake of
correctness) are doing something similar as the code above, but is
running the time function on the entities in serial, not parallel:

The Perl script is:

============= Perl script =============
#!/usr/bin/perl

use strict;
use warnings;

use Clock;

my @clocks = ("clock1", "clock2", "clock3");

foreach my $clock (@clocks) {
my $clock = new Clock();
sleep 1;
print STDOUT "\$clock is: ". $clock->get(), "\n";
}
=======================================

And the Perl module being used is:

============= Perl module: Clock.pm =============
#!/usr/bin/perl

package Clock;

use strict;
use warnings;

sub new {
my ($type) = @_;
my $self = {};
$self->{time} = time();
bless $self, $type;
}

sub get {
my ($self) = shift;
return($self->{time});
}

1;
=======================================

Note the following line of code in the former (non OO) script:

my $thr = threads->new(\&get);

This line is calling the 'get' sub. So, if I were to use the OO
scripts shown, how should I implement this?

I tried doing the obvious, which was to change the line to:

my $thr = threads->new($clock->get());

But I got the following error:

thread failed to start: Undefined subroutine &main::1177952602 called
at ./CC.pl line 19.

Other failed attempts were:

my $thr = threads->new(\&clock->get());
my $thr = threads->new(Clock::clock->get());
my $thr = threads->new($Clock::get());

Truthfully, I am not well versed at Object Oriented Perl (or anything
else). So at this point I was making guesses that weren't so educated.

Does anyone have a solution?

Thanks in advance to all that respond.

Eric
 
M

Martijn Lievaart

Note the following line of code in the former (non OO) script:

my $thr = threads->new(\&get);

This line is calling the 'get' sub. So, if I were to use the OO scripts
shown, how should I implement this?

I tried doing the obvious, which was to change the line to:

my $thr = threads->new($clock->get());

But I got the following error:

thread failed to start: Undefined subroutine &main::1177952602 called at
./CC.pl line 19.

Other failed attempts were:

my $thr = threads->new(\&clock->get()); my $thr =
threads->new(Clock::clock->get()); my $thr =
threads->new($Clock::get());

Truthfully, I am not well versed at Object Oriented Perl (or anything
else). So at this point I was making guesses that weren't so educated.

Does anyone have a solution?

Try (untested):
threads->new(sub { clock->get(); });
or
threads->new(Clock::get, clock);

Your problem is that the method wants a first parameter, the self
parameter or iow the object it is invoked on. You *have* to pass that
parameter, above are two ways of doing that.

HTH,
M4
 
X

xhoster

Eric said:
Note the following line of code in the former (non OO) script:

my $thr = threads->new(\&get);

This line is calling the 'get' sub. So, if I were to use the OO
scripts shown, how should I implement this?

I tried doing the obvious, which was to change the line to:

my $thr = threads->new($clock->get());

But I got the following error:

thread failed to start: Undefined subroutine &main::1177952602 called
at ./CC.pl line 19.

I doubt you will get the performance you think you will out of this
strategy. Starting a new thread for each task is generally a losing
proposition in Perl. Anyway, try:

my $thr = threads->new(sub{$clock->get()});

Xho
 
E

Eric

I doubt you will get the performance you think you will out of this
strategy. Starting a new thread for each task is generally a losing
proposition in Perl. Anyway, try:

my $thr = threads->new(sub{$clock->get()});

Xho

Someone made a similar suggestion, but it seems as if you are
redefining the sub in the file in which it is being called instead of
using it from it's current module(?). Am I missing something here?

Eric
 
X

xhoster

Eric said:
Someone made a similar suggestion, but it seems as if you are
redefining the sub in the file in which it is being called instead of
using it from it's current module(?).

sub{...} creates a new anonymous sub. It can't redefine any existing subs
because to do that, you would need to use the name (or a ref to) an
existing sub, which being anonymous this ones doesn't have.

Xho
 
E

Eric

sub{...} creates a new anonymous sub. It can't redefine any existing subs
because to do that, you would need to use the name (or a ref to) an
existing sub, which being anonymous this ones doesn't have.

Xho

Ok - I can see the rationale behind this. In fact, I tried it, and it
worked. However, I got the oddest response message I've ever seen:

Attempt to free unreferenced scalar: SV 0xafc2db8, Perl interpreter:
0xaa069a0 at <file> <line>

(where 'file' and 'line' were removed in the above).

I should tell you that I got this message running different code than
that which I provided in my posting. So I will need to investigate
what else is going on. I will also try it with the code I posted to
see if I get the same error. But off hand, does the message indicate
anything to you?

Eric
 
E

Eric

Martijn said:
Try (untested):
threads->new(sub { clock->get(); });
or
threads->new(Clock::get, clock);

Your problem is that the method wants a first parameter, the self
parameter or iow the object it is invoked on. You *have* to pass that
parameter, above are two ways of doing that.

HTH,
M4

Thanks for your response. I did in fact try your first suggestion, and
it worked, although I got an odd message (see my reply regarding
this).

I'll give the second one a try also once I determine the source of the
aforementioned odd message.

Eric
 
E

Eric

Eric said:
Ok - I can see the rationale behind this. In fact, I tried it, and it
worked. However, I got the oddest response message I've ever seen:

Attempt to free unreferenced scalar: SV 0xafc2db8, Perl interpreter:
0xaa069a0 at <file> <line>

(where 'file' and 'line' were removed in the above).

I should tell you that I got this message running different code than
that which I provided in my posting. So I will need to investigate
what else is going on. I will also try it with the code I posted to
see if I get the same error. But off hand, does the message indicate
anything to you?

Eric

Scratch this one - I think the error was prompted by something else in
the code.
 
X

xhoster

Eric said:
Ok - I can see the rationale behind this. In fact, I tried it, and it
worked. However, I got the oddest response message I've ever seen:

Attempt to free unreferenced scalar: SV 0xafc2db8, Perl interpreter:
0xaa069a0 at <file> <line>

What version of Perl are you using? I've seen things like that in
some of the early 5.8.x perls that went away in the some of the later
ones.

Xho
 
E

Eric

What version of Perl are you using? I've seen things like that in
some of the early 5.8.x perls that went away in the some of the later
ones.

Xho

I'm using:

$ perl -v

This is perl, v5.8.0 built for i386-linux-thread-multi
(with 1 registered patch, see perl -V for more detail)

Eric
 
X

xhoster

Eric said:
I'm using:

$ perl -v

This is perl, v5.8.0 built for i386-linux-thread-multi
(with 1 registered patch, see perl -V for more detail)

If you want to use threads, you should definitely upgrade. v5.8.0 did
all kinds of misbehavior under threading.

Xho
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top