for the MainLoop documentation. Documentation is sparse, but essentially, it waits until the Glib eventloop is idle, before running the sub, so as not to interfere with it. It is seen used more when you try to use Glib or Gtk2 code from a thread. If you get into GUI's, you will often read about the thread safety of the GUI toolkit. Gtk2's thread safety is accomplished principally by only using Glib::Idle->add to access the main gui code from within the thread. Here are a couple of examples.
#!/usr/bin/perl
use warnings;
use strict;
use Glib;
use Glib qw/TRUE FALSE/;
use threads;
use threads::shared;
my $count = 0;
my $thread;
my $die:shared = 0;
my $main_loop = Glib::MainLoop->new;
#test timer
my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 );
#timer to start thread after 4 seconds
my $timer1 = Glib::Timeout->add (4000, \&timer1_callback, undef, 1 );
#timer to stop thread after 8 seconds
my $timer2 = Glib::Timeout->add (8000, \&timer2_callback, undef, 1 );
$main_loop->run;
sub timer_callback{
$count++;
print "$count\n";
return 1;
}
sub timer1_callback{
$thread = threads->new(\&work);
return 0; #run once only
}
sub timer2_callback{
$die = 1;
$thread->join;
return 0; #run once only
}
sub work{
$|++;
while(1){
foreach my $num (1..1000){
if($die){return}
Glib::Idle->add(
sub{
print "\t\t$num\n";
return FALSE;
});
select(undef,undef,undef, .1);
}
}
}
__END__
and with a GUI
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
use Glib qw/TRUE FALSE/;
use Gtk2 qw/-init -threads-init/;
Glib::Object->set_threadsafe (TRUE);
#setup shared hash
my %shash;
share(%shash); #will work for first level keys
$shash{'go'} = 0;
$shash{'work'} = '';
$shash{'die'} = 0;
my $window = Gtk2::Window->new('toplevel');
$window ->signal_connect( 'destroy' => \&delete_event );
$window->set_border_width(10);
$window->set_size_request(300,300);
my $vbox = Gtk2::VBox->new( FALSE, 6 );
$window->add($vbox);
$vbox->set_border_width(2);
my $hbox= Gtk2::HBox->new( FALSE, 6 );
my $hbox1 = Gtk2::HBox->new( FALSE, 6 );
$vbox->pack_end($hbox,FALSE,FALSE,0);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
$vbox->pack_end($hbox1,FALSE,FALSE,0);
$hbox->set_border_width(2);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
my $ebutton = Gtk2::Button->new_from_stock('gtk-quit');
$hbox->pack_end( $ebutton, FALSE, FALSE, 0 );
$ebutton->signal_connect( clicked => \&delete_event );
my $pbar = Gtk2::ProgressBar->new();
$pbar->set_pulse_step(.1);
$hbox->pack_start($pbar,1,1,0);
my $count = 0;
my $label_w_markup = Gtk2::Label->new();
$label_w_markup->set_markup("<span foreground=\"yellow1\"
size=\"40000\">$count</span>");
$vbox->pack_end($label_w_markup,FALSE,FALSE,4);
######################################################
my $tbutton = Gtk2::Button->new_with_label('Run Thread');
$hbox1->pack_start($tbutton , 1, 1, 0 );
my $lconnect = $tbutton->signal_connect( clicked => sub{ launch() });
my $sconnect;
$window->show_all();
$pbar->hide; #needs to be called after show_all
#create 1 sleeping thread passing it the label and pbar to control
my $thread = threads->new(\&work, $label_w_markup, $pbar);
Gtk2->main;
######################################
sub delete_event {
$shash{'go'} = 0;
$shash{'die'} = 1;
$thread->join;
Gtk2->main_quit;
return FALSE;
}
#######################################
sub launch{
$pbar->show;
$tbutton->set_label('Stop Thread');
$tbutton->signal_handler_block($lconnect);
$sconnect = $tbutton->signal_connect( clicked => sub{ stop() });
$shash{'go'} = 1;
}
##################################################
sub stop{
print "stopped\n";
$shash{'go'} = 0;
$pbar->hide;
$tbutton->set_label('Run Thread');
$tbutton->signal_handler_block ($sconnect);
$tbutton->signal_handler_unblock ($lconnect);
}
#########################################################
sub work{
my ($label,$pbar) = @_;
$|++;
while(1){
if($shash{'die'} == 1){ goto END };
if ( $shash{'go'} == 1 ){
foreach my $num (1..1000){
Glib::Idle->add(
sub{
if($shash{'die'} == 1){ return };
$label->set_markup("<span foreground=\"yellow1\"
size=\"40000\">$num</span>");
$pbar->pulse;
return FALSE;
});
select(undef,undef,undef, .1);
if($shash{'go'} == 0){last}
if($shash{'die'} == 1){ goto END };
}
$shash{'go'} = 0; #turn off self before returning
}else
{ select(undef,undef,undef,.1) } #sleep time
}
END:
}
###########################################################