Description: |
Ever get stuck in a console based app, where you need a nested while(1) loop to sit in a holding pattern, while you watch variables, or filehandles? It is handy to have a Event loop in these cases. You can start the loop anytime in your script, and bust out of it later, to continue linear program flow.
The Gtk2 GUI system, is built upon a non-gui base called Glib.
For unix-like systems, you first need the c-libs installed (Cairo, Glib, Pango, Atk, Gtk2) available at gtk+ Most linux distributions come with these preinstalled, so you can run mozilla, gimp, etc. Once you have the c libs installed, you get the Perl interfaces to them, at Perl/Gtk2 . There are win32 ports at Gtk2-win32
You can use the Glib::MainLoop in console based programs to watch filehandles, run multiple timers( which can do just about anything ), and probably other things which your creativity can come up with. This is the console based version of the MainLoop, which Tk and Gtk2 programmers are familiar with. After you launch the program, start another to write to the test.log file, and see the io_watch monitor the filehandle. Like echo 'yadda yadda' >>test.log |
#!/usr/bin/perl
use warnings;
use strict;
use Glib;
# Glib provides a few ready-made event sources,
# Glib::Timeout, Glib::Idle, and Glib::IO->add_watch
# read perldoc Glib::MainLoop
my $main_loop = Glib::MainLoop->new;
my $count = 1;
my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 );
#my $timer = Glib::Timeout->add ($interval, $callback, $data=undef, $
+pri-
# ority=G_PRIORITY_DEFAULT)
# * $interval (integer) number of milliseconds
# * $callback (subroutine)
# * $data (scalar)
# * $priority (integer)
# Run $callback every $interval milliseconds until $callback return
+s
# false. Returns a source id which may be used with
# "Glib::Source->remove". Note that a mainloop must be active for
# the timeout to execute.
sub timer_callback{
$count++;
print "$count\n";
return 1;
}
my $count1 = 1;
my $timer1 = Glib::Timeout->add (100, \&timer1_callback, undef, 1 );
sub timer1_callback{
$count1++;
print "\t$count1\n";
return 1;
}
### filehandle watch
open (FH, "+> test.log") or warn "$!\n";
Glib::IO->add_watch (fileno 'FH', ['in'], \&watch_callback, 'FH', 1 );
# integer = Glib::IO->add_watch ($fd, $condition, $callback, $data=und
+ef, $priority=G_PRIORITY_DEFAULT)
# * $fd (Glib::IO) file number, e.g. fileno($filehandle)
# * $condition (Glib::IOCondition)
# * $callback (subroutine)
# * $data (scalar)
# * $priority (integer)
$main_loop->run;
####################################################################
sub watch_callback {
my ($fd, $condition, $fh) = @_;
my @lines = <FH>;
print @lines;
#always return TRUE to continue the callback
return 1;
}
Re: Roll your own Event-loop
by elmex (Friar) on Apr 15, 2008 at 09:56 UTC
|
The Tutorial is very nice. But these days there is AnyEvent
on CPAN, which abstracts away any specific event loop.
It has backends for Glib, Tk (*sigh*), EV, Event, Coro
and also it's own pure-Perl implementation (via select).
It's equally useful and as good for quick scripts as for
large applications.
It doesn't matter much for the application, but if you are going to write a module that requires waiting for I/O events, AnyEvent is a very good choice. It doesn't need or
enforce a framework like POE but can still be used by those.
| [reply] |
|
|