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

Hi ...I have a piece of code something like:
while(@xyz) { my @copy = splice(@xyz,0,10); push @xyz_chunk, \@copy; } my @working; while(@xyz_chunk) { my $xyz_chunk = shift @xyz_chunk; @working = @$xyz_chunk; print "debug: @working\n"; }
So essentially, I have @xyz_chunk containing arrays of 10 elements from @xyz. I need to be able to do something like
foreach my $val (@xyz_chunk) { threads->create("sub", $val); }
But this is failing miserably (I need to only create 10 threads at any given time from each xyz_chunk element) and I am at the end of my wits. Any help is highly appreciated!!!!!!! Thanks!

Replies are listed 'Best First'.
Re: Help needed with regard to arrays
by toolic (Bishop) on Nov 20, 2008 at 01:30 UTC
    A handy tool for debugging Perl data structures is Data::Dumper:
    use Data::Dumper; print Dumper(\@xyz_chunk);
Re: Help needed with regard to arrays
by GrandFather (Saint) on Nov 20, 2008 at 01:00 UTC

    In what fashion is it failing? What do you expect to happen and what is happening instead? Can you provide a working code sample that demonstrates the issue?


    Perl reduces RSI - it saves typing
Re: Help needed with regard to arrays
by Corion (Patriarch) on Nov 20, 2008 at 07:43 UTC

    Instead of creating a new thread, create 10 threads which take their work from a central queue:

    my $threadcount = 10; my $jobs = Thread::Queue->new(@xyz); # I use undef as marker when to stop working $jobs->enqueue(undef) for 1..$threadcount; my @workers = map { threads->create( \&work ) } 1..$threadcount; sub work { while (defined (my $item = $jobs->dequeue)) { print "Processing $item\n"; }; };

    But maybe I'm misunderstanding the problem you're trying to solve.

      Hi Corion, With regards to your reply with the thread code, I tried it out and it appears that the threads are asynchronous.....is there a way to make 10 concurrent threads using Thread::Queue? Thanks

        I don't know what you mean by your usage of "asynchronous" as seemingly contrary to "concurrent". Maybe you can describe what problem you're trying to solve or what problem you encounter. Maybe part of the problem is that the sample code doesn't actually spend much time in the threads and hence each thread finishes too quickly. Maybe you want to add a random sleep to each thread.

Re: Help needed with regard to arrays
by johngg (Canon) on Nov 20, 2008 at 11:06 UTC

    Not addressing your threads problem but there are a couple of possible issues with your code.

    • In your first while loop the temporary array @copy is unnecessary, just use the splice inside an anonymous array constructor ([ ... ]). The while could also become a statement modifier if you like (see Statement Modifiers).
    • Choosing the same names for arrays and scalars can be confusing. Perhaps @xyz_chunks and $xyz_chunk would have been better. Some recommend that you name scalars that contain references to something else in an easily identified way, e.g. $raWhatever for an array reference, $rhThose for a hash reference etc. (I tend to use camel-case, others prefer underscores in their identifiers.)
    • There are a couple of points about your second while. It looks like you only use @working inside the loop so it's declaration should be moved inside.
    • Secondly, the while might be better as a foreach so you iterate over each element in turn aliasing it to some scalar (or $_ by default).
    • I second toolic's advice regarding Data::Dumper. It looks like you might be already using strictures since you have declared some of the variables in your code but the advice bears repeating. Always put use strict; and use warnings; at the top of your scripts.

    Here is a short script putting the points mentioned above into practice.

    use strict; use warnings; use Data::Dumper; my @xyz = map { sprintf q{%02d}, $_ } 1 .. 23; my @xyzChunks = (); print Data::Dumper->Dumpxs( [ \ @xyz, \ @xyzChunks ], [ qw{ *xyz *xyzChunks } ] ); print q{=} x 50, qq{\n}; push @xyzChunks, [ splice @xyz, 0, 10 ] while @xyz; print Data::Dumper->Dumpxs( [ \ @xyz, \ @xyzChunks ], [ qw{ *xyz *xyzChunks } ] ); print q{=} x 50, qq{\n}; foreach my $raXyzChunk ( @xyzChunks ) { print qq{Debug: @$raXyzChunk\n}; }

    The output.

    I hope these points are of interest.

    Cheers,

    JohnGG

      Awesome replies! I feel like a novice among Gods.... Thanks all. Specially Corion and JohnGG
Re: Help needed with regard to arrays
by matrixmadhan (Beadle) on Nov 20, 2008 at 04:49 UTC
    foreach my $val (@xyz_chunk) { threads->create("sub", $val); }

    I might be wrong, shouldn't you be dereferencing the array ref before using it
    foreach my $val (@$xyz_chunk) { threads->create("sub", $val); }