Re: non-blocking loop delay
- From: muppet <scott asofyet org>
- To: Grant McLean <grant mclean net nz>
- Cc: Gtk Perl List <gtk-perl-list gnome org>, zentara <zentara zentara net>
- Subject: Re: non-blocking loop delay
- Date: Mon, 13 Jun 2005 08:34:51 -0400
On Jun 12, 2005, at 6:24 PM, Grant McLean wrote:
On Sun, 2005-06-12 at 18:13 -0400, zentara wrote:
Hi,
I'm either missing something, or I'm searching for something which
dosn't
exist. Is there a way to slow down a loop, without blocking the gui?
I know the code below, could (and probably should) be rewritten using
Glib::Timeout->add () instead of a for loop, but what if I wanted
or needed
the for loop.
You can use both, by taking advantage of Perl closures for the 'loop'
index and the fact that if the routine you schedule with Timeout->add
returns TRUE, it will be rescheduled:
That's (arguably) the most idiomatic solution. For completeness,
here are two others:
If your code path is already convoluted, or breaking the operation
out into clean iterations is no so easy, you can retain linear flow
control by inserting a main-loop-based delay. That is, use your own
mainloop to block at the current code point to run the mainloop.
I've found this works well in very deep, complicated things that are
already hard to understand and would only be made worse by turning
them into state machines --- highly interdependent cross cases, lots
of variables, etc.
sub non_blocking_delay {
my $milliseconds = shift;
my $mainloop = Glib::MainLoop->new;
Glib::Timeout->add ($milliseconds, sub { $mainloop->quit;
FALSE; });
$mainloop->run;
}
The advantage is that your code flow stays rather linear. The
disadvantage is that if you need two such things to interleave, this
idiom will get very much in the way. A real state machine allows you
to run arbitrary numbers of these timeouts cleanly.
On the other hand, if what you want isn't so much to run the handler
every so often, but to yield processing in order to break up a long
operation, an idle will make your app more responsive.
sub handle_next_chunk {
my $state = shift;
# do stuff...
return $n_chunks_remaining > 0;
}
...
Glib::Idle->add (handle_next_chunk, $state);
This accomplishes the same thing as Grant's example, but doesn't
insert a delay which is likely longer than necessary. Idles are non-
recursive by default, so this will run whenever the mainloop is idle
until you run out of chunks. I've seen this used to run a "live
video" mode that captures from a video source as fast as possible,
but still responds to gui events.
--
Without treatment, a common cold will last about seven days.
With treatment, it will last about a week.
-- conventional wisdom
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]