Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Perl/Tk App and Interprocess Communication

by beretboy (Chaplain)
on Jun 28, 2005 at 21:14 UTC ( #470827=perlquestion: print w/ replies, xml ) Need Help??
beretboy has asked for the wisdom of the Perl Monks concerning the following question:

I'm working on a Perl/Tk GUI application that displays data coming from another Perl program. The GUI consists of many gKrellM-style graphs and status bar indicators. I'd like to update the graphs as new information comes in (in this case, constantly) without freezing the GUI. So I need some way to trigger Tk events as new information comes from the pipe. I was going to use Tk file events, but apparently these do not work under Windows (the target platform in this case). Is this true and if so, what are my alternatives?

Comment on Perl/Tk App and Interprocess Communication
Re: Perl/Tk App and Interprocess Communication
by zentara (Archbishop) on Jun 29, 2005 at 12:16 UTC
    IPC::Run supposedly works on both Windows and Linux. As a last resort, you could setup a timer to periodocally read what is on the pipe.

    I'm not really a human, but I play one on earth. flash japh
      That's quite a lot of stuff in the "Win32 LIMITATIONS" section in that module's POD. ;)
      But that is the nature of the beast. In Win32, select() only works on sockets, so use those instead of pipes. Tk::fileevent() also doesn't work, so setup a Tk::repeat() callback to invoke your read_socket() function at suitable intervals when $^O eq 'MSWin32' (in Unix context, stick with fileevent though, it's more efficient). read_socket() just calls select() on the socket, and if there's data it goes and does a non-blocking sysread() and dumps that stuff into a buffer (don't forget to check for errors and handle EWOULDBLOCK). You parse the buffer for network-portable EOL sequence (\015\012) and every time you get a whole line of data, you do whatever you need with it.
      It's kind of hairy, and much more complex than what could be done in a pure Unix environment, but at least it works. Other methods may not work so well...
      If you don't already have it, I hightly recommend the book "Network Programming with Perl" (by Lincoln Stein), it explains this stuff very well, and touches on limitations of Win32 and how to get around them. It also has lots of example code, including a multiplexing server, should you need that...
Re: Perl/Tk App and Interprocess Communication
by graff (Chancellor) on Jun 30, 2005 at 02:22 UTC
    I can't provide a test/demo snippet, but you might want to look at Tk::After (or Tk::after); it may be possible to set up a repeating event, at some specified msec interval, which will invoke a callback that you specify. This will be affiliated with some particular widget (might as well be "$mainwindow"), and the callback could include something (I forget what, exactly) that will trigger a cycle of the Tk event loop (refreshing all the widgets).

    The only thing that might be an issue for you is whether you can set up the file handle that reads from the other perl script so that it does non-blocking i/o. That is, if the "Tk::After" event fires, and your callback goes to the file handle to read from that other script, and that script has not produced any output yet, then your Tk GUI will just "wait" (user activity will be stalled) until something comes in on that file handle -- unless the file handle is set up for non-blocking i/o, in which case, a read will always return immediately (and just not provide any data if there was none available).

    That might be the issue that is the basis for the Tk::fileevent limitation to non-MS systems. Good luck.

Re: Perl/Tk App and Interprocess Communication
by didier (Vicar) on Jun 30, 2005 at 06:48 UTC

    You should use the memmap module for win32.
    This allows you to share something via Ram memory between several process.
    Used in conjunction of Tie::Win32MemMap and an the building Tk's timer you can share a hash between any process.

    That's the most efficient way to share something under Tk.
    You can find that module here: http://www.lehigh.edu/~sol0/ptk/ptk.html

    Have fun ;)

Re: Perl/Tk App and Interprocess Communication
by beretboy (Chaplain) on Jun 30, 2005 at 13:39 UTC
    Would doing all this in cygwin solve these problems? Would fileevent work?


    "Sanity is the playground of the unimaginative" -Unknown
Re: Perl/Tk App and Interprocess Communication
by BrowserUk (Pope) on Jun 30, 2005 at 14:29 UTC

    The following demonstrates a Tk app that updates the screen in response to the output from another Perl process in real time:

    #!perl -slw use strict; use threads; use threads::shared; ## A shared var to communicate progress between work thread and TK my $progress : shared = 0; sub work{ open PROC, 'perl -le"$|=1; print and select(undef,undef,undef,0.1) for 1 .. + 1000" |' or die $!; while( <PROC> ) { lock $progress; $progress = $_; } close PROC; } threads->new( \&work )->detach; require Tk::ProgressBar; my $mw = MainWindow->new; my $pb = $mw->ProgressBar()->pack(); my $repeat; $repeat = $mw->repeat( 100 => sub { # print $progress; $repeat->cancel if $progress == 100; $pb->value( $progress ) } ); $mw->MainLoop;

    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?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Thanks for taking the time to write that, you've saved me a huge headache. UPDATE: I've never worked with threads in perl, could you point me towards some resources dealing with that? UPDATE UPDATE: Reading Camel Book chapter now, nevermind. Thanks again! UPDATE UPDATE UPDATE: Okay, I'd really appreciate a walkthrough of how this works, and how you can prevent it from "missing" data. If I bump the timer up to 1 second it jumps over big swaths of numbers.


      "Sanity is the playground of the unimaginative" -Unknown

        Okay. The code I posted will miss intermediate values if the incoming values arrive faster than the screen update checks for them.

        If your application need to reflect every change, and if it can update the screen as fast or faster than the input arrives, that would not occur.

        If you cannot update the screen as fast as the input arrives, then eventually you will have to either combine multiple inputs into a single update, or discard intermediates.

        Either way, to ensure than your update thread sees all the inputs, it must either run faster than the inputs arrive, or they must be queued

        Here is a queued solution.

        #!perl -slw use strict; use threads qw[ async ]; use Thread::Queue; ## A shared var to communicate progess between work thread and TK my $Q = new Thread::Queue; sub work{ open PROC, 'perl -le"$|=1; print and select(undef,undef,undef,0.1) for 1 .. 1 +000" |' or die $!; while( <PROC> ) { $Q->enqueue( $_ ); } close PROC; } threads->new( \&work )->detach; ## For lowest memory consumption require (not use) ## Tk::* after you've started the work thread. require Tk::ProgressBar; my $mw = MainWindow->new; my $pb = $mw->ProgressBar()->pack(); my $repeat; $repeat = $mw->repeat( 100 => sub { while( $Q->pending ) { my $progress = $Q->dequeue; return unless $progress; $repeat->cancel if $progress == 100; $pb->value( $progress ) } } ); $mw->MainLoop;

        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?
        "Science is about questioning the status quo. Questioning authority".
        The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://470827]
Approved by injunjoel
Front-paged by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (10)
As of 2014-09-16 03:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (155 votes), past polls