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

I have a bunch of filehandles and I'm reading from them.

What I want to do is to wait until something is available at one of them, but I don't feel like constantly trying to read from them all...

What I'd like to do would be to assign a function to each of the filehandles I have. When a new line was made available at one of them, the corresponding function would be executed with whatever was in the filehandle.

Thoughts, anyone?

Replies are listed 'Best First'.
Re: Waiting for multiple filehandles
by Corion (Patriarch) on Mar 22, 2005 at 12:02 UTC

    The low level approach would be select, which does exactly that, and on Unix systems also works on filehandles. On Win32, you would have to use WaitForMultipleObjects to get select-like functionality.

    But most likely, you want a framework that calls your function(s) whenever something interesting happens, and POE is such a framework. Most likely POE::Wheel::File::Tail does what you want.

Re: Waiting for multiple filehandles
by Fletch (Bishop) on Mar 22, 2005 at 13:38 UTC

    There's also IO::Select which provides an OOPy wrapper around the lower level call. But definitely check out POE.

Re: Waiting for multiple filehandles (threads)
by BrowserUk (Patriarch) on Mar 22, 2005 at 14:34 UTC

    Here's how I do it using threads:

    #! perl -slw use strict; use threads; use threads::shared; use Thread::Queue; my $Qin = new Thread::Queue; my $done :shared = 0; async{ open my $fh1, '<', "firewall.log" or die "FWLog : $!"; ( local $_ = <$fh1> and $Qin->enqueue( "F1:$_") ) or Win32::Sleep 10 until $done; close $fh1; }; async{ open my $fh2, '<', "modem.log" or die "Modemlog : $!"; ( local $_ = <$fh2> and $Qin->enqueue( "F2:$_" ) ) or Win32::Sleep 10 until $done; close $fh2; }; while( my $input = $Qin->dequeue() ) { chomp $input; my( $src, $txt ) = split ':', $input, 2; if( $src eq 'F1' ) { print "Firewall: '$txt'"; } else { print "Modem : '$txt'"; } }

    This monitors 2 files, and processes all the data in a single place. It is easy to extend to any number of files and you can process the data within the threads rather than centrally if that fits your needs.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco.
    Rule 1 has a caveat! -- Who broke the cabal?
      cool script!
      where can i find some nice tutorials about threads and using in perl? i understand that the async starts up the code in parallel with other async code blocks..

      and why do you have the $done shared? it's not being set to 1 anywhere, so i was just wondering...

      but .. your script gives many insights thanks ;-)

      --
      to ask a question is a moment of shame
      to remain ignorant is a lifelong shame

        Anyone using threads in Perl should read Things you need to know before programming Perl ithreads.

        Update: I guess I should clarify my position a bit, since I seem to have ruffled BrowserUk's feathers with this post. For me, personally, myself, in my code, on my machine, I agree with merlyn. I might consider using lightweight threads, but Perl's are not. They seem like a bad imitation of a real fork. I think the design of Perl's threads is broken, not the idea of threads in general.

        That being said, I was not trying to persuade anybody not to use threads. If I was, I would have said so. I was simply trying to refer to an article that brings up an important caveat about Perl's threads. As I said later, I think it's important that people know about this caveat. It makes Perl's threads -- as designed and implemented -- distinct from the common understanding of what threads are, and it deserves to be highlighted and explained to folks who are using them.

          A reply falls below the community's threshold of quality. You may see it by logging in.
        and why do you have the $done shared? it's not being set to 1 anywhere, so i was just wondering

        Because, for clarity, I cut down an existing script which monitors my firewall and modem logs. In the real script, the main thread also traps SIGINT, sets $done true and waits for the threads to terminate before ending.

        I don't know of any good "perl + threads" tutorials. You could do a super search for my posts that contain "use threads", there are quite a few examples now, but be warned, I am still learning what is and is not possible to do and the best ways of doing things. Many of my earlier threads posts contain code which is moe complicated that necessary.

        I'd try and put together some kind of tutorial on them, but I've only use threads and Perl on Win32. I have seen very little information about what works on other platforms, so it would have very limited scope.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco.
        Rule 1 has a caveat! -- Who broke the cabal?