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

hello all, i am getting the following error when i am trying to run my 1st Perl script:
[id=0 @ 0] : IP address "3.3.3.3" corresponds to device "core". Thread 1 terminated abnormally: Not a CODE reference at ./dev_ithread. +pl line 23. [id=0 @ 1] : IP address "5.5.5.5" corresponds to device "border". Thread 2 terminated abnormally: Not a CODE reference at ./dev_ithread. +pl line 23.
and here is what i have written so far:
#!/usr/bin/perl use strict ; use warnings ; use diagnostics ; use threads ; use Config ; $Config{useithreads} || die("\n---> Please recompile Perl with \<ithre +ads\> included. \n") ; # IP parameterization of network elements. my %device_ip = ( "core" => "3.3.3.3", "border" => "5.5.5.5", ) ; # Initialize devices' pool of threads. my $index = 0 ; my @device_thread = () ; while( my ($key, $value) = each %device_ip ) { push( @device_thread, threads->new(\&thread_job($key, $device_ip{$ +key}, $index))->join ) ; $index = $index+1 ; } # Worker thread subroutine. sub thread_job { my ($device, $ip, $index) = @_ ; my $ithread = threads->tid() ; print "[id=$ithread @ $index] : IP address \"$ip\" corresponds to +device \"$device\". \n" ; }
i would be thankful, if someone could help me overcome this problem. thank you.

Replies are listed 'Best First'.
Re: Not a CODE reference … my 1st script
by wind (Priest) on Apr 03, 2011 at 20:35 UTC
    You can't take a reference to a subroutine and initiate it by passing parameters at the same time. Use an anonymous sub instead.
    push @device_thread, threads->new(sub {thread_job($key, $device_ip{$ke +y}, $index)})->join;
Re: Not a CODE reference … my 1st script
by BrowserUk (Patriarch) on Apr 03, 2011 at 22:43 UTC

    This:

    push( @device_thread, threads->new( \&thread_job( $key, $device_ip{$key}, $index ) )->join ) ;
    1. Calls the function thread_job() passing some parameters;
    2. Then starts a thread to run a reference to the return value from the sub.

      Which obviously fails because the return value isn't a code reference, hence the error message.

    3. which it joins immediately,

      Meaning that the calling thread would block waiting for the child thread to complete. Which would be exactly equivalent, but much more expensive that calling the function inline.

    4. And then push the return value from the thread onto the array.

      Is that what you intended, or were you meaning to push the thread handles onto the array call @device_thread?

    Your code is so confused, that it is hard to know quite what your intention was, but I suspect that you might want:

    push( @device_thread, threads->new( \&thread_job, $key, $device_ip{$key}, $index ) ); ... $__>join for @threads;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      many thanks to both of you. both solutions worked :)
Re: Not a CODE reference … my 1st script
by educated_foo (Vicar) on Apr 04, 2011 at 05:30 UTC
    You seem to be exhibiting Perlmonks Stockholm syndrome. Your code doesn't have to be that hideous:
    use threads; my %device_ip = ( core => "3.3.3.3", border => "5.5.5.5", ); # Initialize devices' pool of threads. my $index = 0; my @th; while (my ($k, $v) = each %device_ip) { push @th, threads->new(\&thread_job, $k, $device_ip{$k}, $index++) } $_->join for @th; # Worker thread subroutine. sub thread_job { my ($dev, $ip, $i) = @_; my $tid = threads->tid(); print qq![id=$tid @ $i]: IP address "$ip" corresponds to device "$ +dev".\n!; }
      You seem to be exhibiting Perlmonks Stockholm syndrome. Your code doesn't have to be that hideous

      Its better than code beauty judge