in reply to Non Blocking input on Win32 platforms

For a simple threaded example that doesn't require any graphics libraries to be downloaded*, see Re^3: How to Multiplex a Client using IO::Select.

(*why would it once you're using a thread?)


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."
  • Comment on Re: Non Blocking input on Win32 platforms

Replies are listed 'Best First'.
Re^2: Non Blocking input on Win32 platforms
by TGI (Parson) on Oct 31, 2008 at 21:41 UTC

    It's worth mentioning that select only works on sockets under win32. Win32::Socketpair, provides a work around.

    I've been working with Win32::Socketpair and I ran into a few snags. I haven't had time to contact the author with a proper bug report yet, but it is important to know that because winopen2 uses system(1, ...) to spawn child processes, you can only launch 64 processes under windows before it stops working. It is a simple matter to change the code to use Win32::Process::Create to spawn children. The other snag that I just encountered yesterday and haven't found a work around for yet is that using PerlApp 6 to bind your executables as GUI programs, means that STDIO to any children gets messed up in some mysterious way.

    With those caveats, IO::Select makes it easy to do non-blocking IO.


    TGI says moo

        It appears that my reading comprehension was poor yesterday. I've been fighting my own issues with stdio on windows (actually it seems to be related to issues of console inheritance and wperl), and it seems to have distorted my perception of the OP's problem.

        You are correct, it makes no sense to spawn a second process just to create a selectable IO source. But, I wasn't advocating that approach. Despite the fact that I communicated so poorly as to make it sound like I was.

        I recall our earlier exchange perfectly well.

        My comments on Win32::Socketpair (note the 'p') stem from the fact that you referenced a thread where it was discussed as a possible solution. In this context, I felt that sharing the shortcomings of Win32::Socketpair that I had recently discovered may be helpful.


        TGI says moo

Re^2: Non Blocking input on Win32 platforms
by zentara (Cardinal) on Nov 01, 2008 at 13:06 UTC
    that doesn't require any graphics libraries to be downloaded*

    Once again, Glib is NOT a graphics library, it is a basic eventloop system, upon which the Gtk2 graphic system is based. The eventloop system makes it easier to watch the filehandle from the main thread, AND to do other things in the main thread without a cumbersome while(1) loop. It also works cross-platform, which can't be said for the Win32 modules.


    I'm not really a human, but I play one on earth Remember How Lucky You Are

      Let's see what you are advocating here.

      use Glib; use Term::ReadKey; use threads; #use threads::shared; $|++; ReadMode('cbreak'); # works non-blocking if read stdin is in a thread my $count = 0; my $thr = threads->new(\&read_in)->detach; my $main_loop = Glib::MainLoop->new; my $timer = Glib::Timeout->add (1000, \&timer_callback, undef, 1 ); # can also have filehandle watches #my $watcher; #$watcher = Glib::IO->add_watch( fileno( $pty ), ['in', 'hup'], \&call +back); $main_loop->run; ReadMode('normal'); # restore normal tty settings sub timer_callback{ #do stuff $count++; print "\n$count\n"; return 1; } sub read_in{ while(1){ my $char; if (defined ($char = ReadKey(0)) ) { print "\t\t$char->", ord($char),"\n"; #process key presses here #if($char eq 'q'){exit} if(length $char){exit} # panic button on any key :-) } } }
      1. use threads;
      2. and use Term::ReadKey;
      3. and use Glib;
      4. and my $timer  = Glib::Timeout->add (1000, \&timer_callback, undef, 1 );
      5. and (despite your "...without a cumbersome while(1) loop."), while(1){

      And what does all of that get you? Not a lot!

      You still have to write your own line editing, command line history, command line aliases etc. etc.

      And if you need to do something that'l take a few seconds, your going to have to break it up into iddy biddy chunks, or lace it through with some do_one_event() call or similar.

      when the alternative is:

      my $Qstdin = new Thread::Queue; async { $Qstdin->enqueue( $_ ) while defined( $_ = <STDIN> ); }->detach; ... my $kbinput = $Qstdin->dequeue;

      Fully cross platform; one thread and no faffing around with iddy biddy callbacks; and all the command line handling your local shell provides--that works in exactly whatever way the local shell provides it.

      AND to do other things in the main thread

      Rubbish! As soon as you enter that MainLoop-run, your main "thread" is dead until something signals stop.

      And you might want to revise your "It also works cross-platform,". From the GLib docs:

      The GIOChannel data type aims to provide ... support for Windows is only partially complete.
      which can't be said for the Win32 modules.

      Oh! And what Win32 modules would that be?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        First I clearly said in my original response The solution is to spawn a thread to read STDIN, see Readkey with timer using Glib. You may not need the Glib stuff

        So I posted an example I had, which used a lib that you don't like, and clearly said you may not need the Glib stuff, the secret is to put the STDIN watcher in a thread. I figured a poster that asked a question like that could understand the value of reading a single key from STDIN in a non-blocking manner.

        But instead of accepting that as 1 way to solve the STDIN problem( and is a preferred way on linux, to avoid select and multiple select timeouts), you chose to jump on the Glib module, for some reason, possibly because you don't like it. Probably because it was not designed for Win32 exclusively, which you seem to prefer. Or maybe you don't understand the concept that a snippet may be posted to demonstrate a principle, but not give an exact answer. The Term::Readkey was invoked to read a single key, rather than line input, and was mentioned by the OP, so it is fair to include. Thread::Queue ?? I can't stand that module, but do I respond to your posts advocating it's use as waste and source of problems?

        You said: And if you need to do something that'l take a few seconds, your going to have to break it up into iddy biddy chunks, or lace it through with some do_one_event() call or similar.

        Clearly you havn't read the docs for the Glib module, Idle->add() will add anything you want into the loop one time, you don't need a timer for everything.

        You said:Rubbish! As soon as you enter that MainLoop-run, your main "thread" is dead until something signals stop.

        For as smart as you seem to be in your other answers, you show a complete ignorance of eventloop systems. Maybe you are just having a bad day. My guess is that you are stuck on win32, and don't want to expand your horizons, like most MSjunkies.

        You said: Oh! And what Win32 modules would that be?

        Win32::SocketPair


        I'm not really a human, but I play one on earth Remember How Lucky You Are