From the gtk2-perl maillist ( the best place for deep questions):
# wise words of muppet ##############################
That example predates some other important developments in threading
support...
You want to have:
use Gtk2 '-init', '-threads-init';
The -threads-init import option is equalivent to calling
Gtk2::Gdk::Threads->init(). This makes the calls to
Gtk2::Gdk::Threads->enter() and Gtk2::Gdk::Threads->leave() actual
+ly
have effect for wrapping calls to gui functions from child threads
+;
see the C reference docs for gdk_threads_enter() and gdk_threads_l
+eave
().
You'll also want to call Glib::Object->set_threadsafe (TRUE); befo
+re
doing much of anything; this enables object tracking within the
bindings, to avoid the "object destroyed out from under you"
problem. The bindings must be built with thread support, which is
+
the default.
Note, however, that i have not personally played with this thread-
+
safety stuff to any degree, so YMMV.
#####################################
back to me
.... from what i recall in my testing, the "init" stuff, is more intended for ref counts and object safety across threads
... whearas the "enter" "leave" stuff, is an attempt at thread safety as the program runs, where you are indicating that you intended to enter the thread, and manipulate
it only..... this is problem prone...and complex, like the main thread must be entered and left also
.... the general advice from the c gurus is to use glib idle_add, which informs the mainloop to only run that code at the next convenient time..... the code can be dynamically named external subs..
an example
#!/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__
#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.
|