Re: Question about behaviour of foreach and Glib:IO-> add_handler




Mike Martin wrote:
Hi

I was always under the impression that a foreach loop iterated over a
list sequentially, which in every other case at least seems to happen.

However I have the following code

     foreach file
         run command on file

Which runs the following sub-routine (abrev) for each file ($files above)

sub run_cmd {
$pid=open($file, "-|","$cmd{$subname} 2>&1") or die "Failed running
perl subprocess\n";

This forks a child that runs concurrently....

   [snip text buffer setup]

our $tag=  Glib::IO->add_watch ( fileno($file), ['in', 'hup'], sub {
        [snip]
        }
        );

This installs a callback to be run by the main loop when data arrives on the
file handle connected to the child's output, or when that file hangs up.


}

And then you return.


Which means that all run_cmd() actually does is fork the child and set up the
main loop to listen to it.  It does not wait, irrespective of what the
callback does.


However the sub is run for each file in parallel. Anyone have any idea
how to force sequential mode?

You need to keep the UI responsive while this is happening, so you must run a
main loop.  You can run a main loop at the end of run_cmd() to keep the
control flow stopped there until either the child completes and kills the main
loop, or a cancel button causes you to kill the child and quit that nested
main loop.  E.g.:

  sub run_cmd  {

      my $file = open_child_process (...);

      Glib::IO->add_watch (fileno ($file), ['in', 'hup'], sub {
                     my (undef, $cond) = @_;
                     if (user_wants_to_cancel ()) {
                         kill_child ();
                         # let this proceed naturally; we'll get another
                         # call with HUP next time around.
                     }
                     if ($cond >= 'in') {
                         handle_the_input_data ();
                     }
                     if ($cond >= 'hup') {
                         close ($file);
                         # Kill the nested main loop, see below
                         Gtk2->main_quit ();
                         return FALSE;
                     }
                     return TRUE;
                });

      # Now wait here for the IO watch to kill this nested main loop.
      Gtk2->main ();

    }



-- 
muppet <scott at asofyet dot org>




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]