With a Testit.pm that looks like this:

package Testit; require Exporter; our @ISA = qw[ Exporter ]; our @EXPORT = qw[ forthread ]; our @VERSION = 1.0; sub forthread{ my ($arg)=@_; warn "forthread called with argument: '$arg'"; return 0; } 1;

And a test.pl that looks like this:

#! perl -w use strict; use threads; use XML::Simple; use Data::Dumper; my $data = ' <cde> <thread> <module>Testit</module> <subroutine>forthread</subroutine> </thread> </cde> '; my $ref = XMLin( $data ); print Dumper $ref; my $argument=1; require $ref->{thread}{module} . '.pm'; ## Line A my $thread=threads->create( \&{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} }, +# Line B $argument ); $thread->join(); exit(0);

I get the following output:

c:\test>test $VAR1 = { 'thread' => { 'subroutine' => 'forthread', 'module' => 'Testit' } }; forthread called with argument: '1' at Testit.pm line 11.

The salient parts of this are lines A & B

  1. require $ref->{thread}{module} . '.pm';

    This concatenates the module name from the XML with '.pm' and then requires the module.

    Omitting the '.pm' from the XML simplifies the next line, but you could include it if it was important. You'd just have to strip it away for the next bit.

  2. \&{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} },

    This builds a string from the module name and subroutine name:

    $ref->{thread}{module} . '::' . $ref->{thread}{subroutine}

    Note: It means you don't have to export the function from the module, thereby avoiding polluting your main, and the risk of conflicts where two more modules export the same subroutine.

    It then asks Perl to treat that string as the name of a subroutine by placing it inside &( ... }:

    &{ 'Testit::forthread' }

    And finally (and subtly), it asks for a reference to that subroutine

    \ &{ 'Testit::forthread' }

    Without the \, the &{ 'subroutine' } construct would immediately call the subroutine named, and it would be the return value from the subroutine that would be passed to threads->create(). Which wouldn't do at all. The backslash tells perl to not invoke the subroutine, but rather return a coderef to instead.

Interestingly, if you wanted to invoke the subroutine via the &{ ... } construct, and are useing strict, then you would have to disable strict for this with no strict 'refs';, as this is a symbolic reference. However, by asking for a coderef, it appears to bypass the strict detection mechanisms and lets you get away without disabling strict. I only discovered this because I reused your early code which didn't have strict enabled.

You might want to add the no strict 'refs'; anyway, as it would act as a warning/reminder that something unusual is going on here. Eg.

require $ref->{thread}{module} . '.pm'; my $thread=threads->create( do{ no strict 'refs'; \ &{ $ref->{thread}{module} . '::' . $ref->{thread}{subroutine} } }, $argument );

Here the do{ .. } block serves to confine the effects of the no strict 'refs' to exactly that piece of code where it is(n't :) needed.

You could of course, assign the concatenated name to a variable and the substitute that variable for the string:

require $ref->{thread}{module} . '.pm'; my $subname = $ref->{thread}{module} . '::' . $ref->{thread}{subroutin +e}; my $thread=threads->create( do{ no strict 'refs'; \ &{ $subname } }, $argument );

if you feel that clarifies things. Many here would, and looking again at the above, in this case I might agree with them.


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.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

In reply to Re^5: "Attempt to free unreferenced scalar" and "Scalars leaked: 1" ? by BrowserUk
in thread "Attempt to free unreferenced scalar" and "Scalars leaked: 1" ? by licht

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.