Re: non-blocking loop delay




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]